Line data Source code
1 : //
2 : // Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3 : //
4 :
5 : #include <utility>
6 : #include <string>
7 : #include <vector>
8 : #include <boost/asio/buffer.hpp>
9 : #include <boost/intrusive_ptr.hpp>
10 : #include <boost/algorithm/string.hpp>
11 :
12 : #include <sandesh/sandesh_message_builder.h>
13 :
14 : #include <base/logging.h>
15 : #include "base/address_util.h"
16 : #include <io/io_types.h>
17 : #include <io/tcp_server.h>
18 : #include <io/tcp_session.h>
19 : #include <io/udp_server.h>
20 :
21 : #include <rapidjson/document.h>
22 : #include <rapidjson/stringbuffer.h>
23 : #include <rapidjson/writer.h>
24 :
25 : #include "structured_syslog_server.h"
26 : #include "structured_syslog_server_impl.h"
27 : #include "generator.h"
28 : #include <analytics/sdwan_uve_types.h>
29 : #include "syslog_collector.h"
30 : #include "structured_syslog_config.h"
31 :
32 :
33 : using std::make_pair;
34 :
35 : namespace structured_syslog {
36 :
37 : namespace impl {
38 :
39 :
40 : void StructuredSyslogDecorate(SyslogParser::syslog_m_t &v, StructuredSyslogConfig *config_obj,
41 : boost::shared_ptr<std::string> msg, std::vector<std::string> int_fields);
42 : void StructuredSyslogPush(SyslogParser::syslog_m_t v, StatWalker::StatTableInsertFn stat_db_callback,
43 : std::vector<std::string> tagged_fields);
44 : void StructuredSyslogUVESummarize(SyslogParser::syslog_m_t v, bool summarize_user, StructuredSyslogConfig *config_obj);
45 : boost::shared_ptr<std::string> StructuredSyslogJsonMessage(SyslogParser::syslog_m_t v);
46 :
47 0 : size_t DecorateMsg(boost::shared_ptr<std::string> msg, const std::string &key, const std::string &val, size_t prev_pos) {
48 0 : if (msg == NULL) {
49 0 : return 0;
50 : }
51 0 : size_t pos = msg->find(']', prev_pos);
52 0 : if (pos == std::string::npos) {
53 0 : return 0;
54 : }
55 0 : std::string insert_str = " " + key + "=\"" + val + "\"";
56 0 : msg->insert(pos, insert_str);
57 0 : return pos;
58 0 : }
59 :
60 0 : bool ParseStructuredPart(SyslogParser::syslog_m_t *v, const std::string &structured_part,
61 : const std::vector<std::string> &int_fields, boost::shared_ptr<std::string> fwd_msg){
62 0 : std::size_t start = 0, end = 0;
63 0 : size_t prev_pos = 0;
64 0 : while ((end = structured_part.find('=', start)) != std::string::npos) {
65 0 : const std::string key = structured_part.substr(start, end - start);
66 0 : start = end + 2;
67 0 : end = structured_part.find('"', start);
68 0 : if (end == std::string::npos) {
69 0 : LOG(ERROR, "BAD structured_syslog: " << structured_part);
70 0 : return false;
71 : }
72 0 : const std::string val = structured_part.substr(start, end - start);
73 0 : LOG(DEBUG, "structured_syslog - " << key << " : " << val);
74 0 : start = end + 2;
75 0 : if (std::find(int_fields.begin(), int_fields.end(),
76 0 : key) != int_fields.end()) {
77 0 : LOG(DEBUG, "int field - " << key);
78 0 : int64_t ival = atol(val.c_str());
79 0 : v->insert(std::pair<std::string, SyslogParser::Holder>(key,
80 0 : SyslogParser::Holder(key, ival)));
81 : } else {
82 0 : v->insert(std::pair<std::string, SyslogParser::Holder>(key,
83 0 : SyslogParser::Holder(key, val)));
84 : }
85 0 : prev_pos = DecorateMsg(fwd_msg, key, val, prev_pos);
86 0 : }
87 0 : return true;
88 : }
89 :
90 0 : bool filter_msg(SyslogParser::syslog_m_t &v) {
91 0 : std::string tag = SyslogParser::GetMapVals(v, "tag", "UNKNOWN");
92 0 : std::string reason = SyslogParser::GetMapVals(v, "reason", "UNKNOWN");
93 0 : if (tag == "APPQOE_BEST_PATH_SELECTED" &&
94 0 : ((reason == "session close") || reason == "app detected")) {
95 0 : return false;
96 : }
97 0 : if (tag == "SNMP_TRAP_LINK_UP" || tag == "SNMP_TRAP_LINK_DOWN") {
98 0 : if (SyslogParser::GetMapVals(v, "role", "UNKNOWN") == "HUB" &&
99 0 : SyslogParser::GetMapVals(v,"interface-name", "UNKNOWN").compare(0, 2, "st") != 0) {
100 0 : return false;
101 : }
102 : }
103 0 : return true;
104 0 : }
105 :
106 : //filter out session close syslog for incoming traffic i.e. syslog coming from destination site.
107 0 : bool filter_session_close_msg(SyslogParser::syslog_m_t &v) {
108 0 : std::string routing_instance = SyslogParser::GetMapVals(v, "routing-instance", "UNKNOWN");
109 0 : if (routing_instance.size() > 3 && ( routing_instance.compare(0,4,"LAN-") == 0)) {
110 0 : return true;
111 : }
112 0 : return false;
113 0 : }
114 :
115 : //filter out vol update syslog for incoming traffic i.e. syslog coming from destination site.
116 0 : bool filter_vol_update_msg(SyslogParser::syslog_m_t &v) {
117 0 : std::string department = SyslogParser::GetMapVals(v, "source-zone-name", "UNKNOWN");
118 0 : if ((department.compare(0,5,"trust") == 0) || (department.compare(0,7,"untrust") == 0)) {
119 0 : return true;
120 : }
121 0 : return false;
122 0 : }
123 :
124 31 : bool StructuredSyslogPostParsing (SyslogParser::syslog_m_t &v, StructuredSyslogConfig *config_obj,
125 : StatWalker::StatTableInsertFn stat_db_callback, const uint8_t *message,
126 : int message_len, boost::shared_ptr<StructuredSyslogForwarder> forwarder){
127 : /*
128 : syslog format: <14>1 2016-12-06T11:38:19.818+02:00 csp-ucpe-bglr51 RT_FLOW: APPTRACK_SESSION_CLOSE [junos@2636.1.1.1.2.26
129 : reason="TCP RST" source-address="4.0.0.3" source-port="13175" destination-address="5.0.0.7"
130 : destination-port="48334" service-name="None" application="HTTP" nested-application="Facebook"
131 : nat-source-address="10.110.110.10" nat-source-port="13175" destination-address="96.9.139.213"
132 : nat-destination-port="48334" src-nat-rule-name="None" dst-nat-rule-name="None" protocol-id="6"
133 : policy-name="dmz-out" source-zone-name="DMZ" destination-zone-name="Internet" session-id-32="44292"
134 : packets-from-client="7" bytes-from-client="1421" packets-from-server="6" bytes-from-server="1133"
135 : elapsed-time="4" username="Frank" roles="Engineering" encrypted="No" profile-name="pf1" rule-name="1"
136 : routing-instance="inst1" destination-interface-name="xe-1/2/0.0"]
137 : */
138 :
139 : /*
140 : Remove unnecessary fields so that we avoid writing them into DB
141 : */
142 31 : v.erase("msglen");
143 31 : v.erase("severity");
144 31 : v.erase("facility");
145 31 : v.erase("year");
146 31 : v.erase("month");
147 31 : v.erase("day");
148 31 : v.erase("hour");
149 31 : v.erase("min");
150 31 : v.erase("sec");
151 31 : v.erase("msec");
152 31 : if (SyslogParser::GetMapVal(v, "pid", -1) == -1)
153 31 : v.erase("pid");
154 :
155 62 : const std::string body(SyslogParser::GetMapVals(v, "body", ""));
156 31 : std::size_t start = 0, end = 0;
157 31 : v.erase("body");
158 31 : LOG(DEBUG, "BODY: " << body);
159 31 : end = body.find('[', start);
160 31 : size_t tag_end = end;
161 :
162 31 : if (end == std::string::npos) {
163 0 : LOG(ERROR, "BAD structured_syslog: " << body);
164 0 : return false;
165 : }
166 31 : end = body.find(']', end+1);
167 :
168 31 : if (end == std::string::npos) {
169 1 : LOG(ERROR, "BAD structured_syslog: " << body);
170 1 : return false;
171 : }
172 30 : end = body.find(' ', start);
173 :
174 30 : if (end == std::string::npos) {
175 0 : LOG(ERROR, "BAD structured_syslog: " << body);
176 0 : return false;
177 : }
178 30 : std::string tag_ = "UNKNOWN";
179 30 : std::string find_tag_str = body.substr(start,tag_end-1);
180 30 : std::size_t tag_index = find_tag_str.find_last_of(' ');
181 30 : if (tag_index != std::string::npos){
182 2 : tag_ = find_tag_str.substr(tag_index+1, end-tag_index);
183 : }
184 28 : else {tag_ = find_tag_str;}
185 30 : const std::string tag = tag_;
186 30 : LOG(DEBUG, "structured_syslog - tag: " << tag );
187 30 : boost::shared_ptr<MessageConfig> mc = config_obj->GetMessageConfig(tag);
188 30 : if (mc == NULL || ((mc->process_and_store() == false) && (mc->forward() == false)
189 0 : && (mc->process_and_summarize() == false))) {
190 30 : LOG(DEBUG, "structured_syslog - not processing message: " << tag );
191 30 : return false;
192 : }
193 0 : LOG(DEBUG, "structured_syslog - message_config: " << mc->name());
194 0 : boost::shared_ptr<std::string> msg;
195 0 : boost::shared_ptr<std::string> hostname;
196 0 : start = tag_end;
197 :
198 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("tag",
199 0 : SyslogParser::Holder("tag", tag)));
200 :
201 0 : end = body.find(' ', start);
202 :
203 0 : if (end == std::string::npos) {
204 0 : LOG(ERROR, "BAD structured_syslog: " << body);
205 0 : return false;
206 : }
207 0 : const std::string hardware = body.substr(start+1, end-start-1);
208 :
209 0 : start = end + 1;
210 0 : LOG(DEBUG, "structured_syslog - hardware: " << hardware);
211 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("hardware",
212 0 : SyslogParser::Holder("hardware", hardware)));
213 0 : end = body.find_last_of(']');
214 0 : std::string structured_part = body.substr(start, end-start);
215 0 : LOG(DEBUG, "structured_syslog - struct_data: " << structured_part);
216 :
217 0 : bool ret = ParseStructuredPart(&v, structured_part, mc->ints(), msg);
218 0 : if (ret == false){
219 0 : return ret;
220 : }
221 : // Do not process APPTRACK_SESSION_CLOSE syslogs for incoming traffic
222 0 : if(tag == "APPTRACK_SESSION_CLOSE" && filter_session_close_msg(v)){
223 0 : return false;
224 : }
225 :
226 : // Do not process APPTRACK_SESSION_VOL_UPDATE syslogs for incoming traffic.
227 0 : if(tag == "APPTRACK_SESSION_VOL_UPDATE" && filter_vol_update_msg(v)) {
228 0 : return false;
229 : }
230 :
231 0 : if (mc->process_and_store() == true || mc->process_before_forward() == true
232 0 : || mc->process_and_summarize() == true) {
233 0 : if (forwarder != NULL && mc->forward() == true) {
234 0 : msg.reset(new std::string (message, message + message_len));
235 0 : hostname.reset(new std::string (SyslogParser::GetMapVals(v, "hostname", "")));
236 : }
237 0 : StructuredSyslogDecorate(v, config_obj, msg, mc->ints());
238 0 : if (mc->process_and_summarize() == true) {
239 0 : bool syslog_summarize_user = mc->process_and_summarize_user();
240 0 : StructuredSyslogUVESummarize(v, syslog_summarize_user, config_obj);
241 : }
242 0 : if (forwarder != NULL && mc->forward() == true &&
243 0 : mc->process_before_forward() == true && filter_msg (v)) {
244 0 : std::stringstream msglength;
245 0 : msglength << msg->length();
246 0 : msg->insert(0, msglength.str() + " ");
247 0 : LOG(DEBUG, "forwarding after decoration - " << *msg);
248 0 : boost::shared_ptr<std::string> json_msg;
249 0 : if (forwarder->kafkaForwarder()) {
250 0 : json_msg = StructuredSyslogJsonMessage(v);
251 : }
252 0 : boost::shared_ptr<StructuredSyslogQueueEntry> ssqe(new StructuredSyslogQueueEntry(msg, msg->length(),
253 0 : json_msg, hostname));
254 0 : forwarder->Forward(ssqe);
255 0 : }
256 0 : if (mc->process_and_store() == true) {
257 0 : StructuredSyslogPush(v, stat_db_callback, mc->tags());
258 : }
259 : }
260 0 : if (forwarder != NULL && mc->forward() == true && filter_msg(v) &&
261 0 : mc->process_before_forward() == false) {
262 0 : msg.reset(new std::string (message, message + message_len));
263 0 : hostname.reset(new std::string (SyslogParser::GetMapVals(v, "hostname", "")));
264 0 : std::stringstream msglength;
265 0 : msglength << msg->length();
266 0 : msg->insert(0, msglength.str() + " ");
267 0 : LOG(DEBUG, "forwarding without decoration - " << *msg);
268 0 : boost::shared_ptr<std::string> json_msg;
269 0 : if (forwarder->kafkaForwarder()) {
270 0 : json_msg = StructuredSyslogJsonMessage(v);
271 : }
272 0 : boost::shared_ptr<StructuredSyslogQueueEntry> ssqe(new StructuredSyslogQueueEntry(msg, msg->length(),
273 0 : json_msg, hostname));
274 0 : forwarder->Forward(ssqe);
275 0 : }
276 0 : return true;
277 31 : }
278 :
279 0 : static inline void PushStructuredSyslogAttribsAndTags(DbHandler::AttribMap *attribs,
280 : StatWalker::TagMap *tags, bool is_tag, const std::string &name,
281 : DbHandler::Var value) {
282 : // Insert into the attribute map
283 0 : attribs->insert(make_pair(name, value));
284 0 : if (is_tag) {
285 : // Insert into the tag map
286 0 : StatWalker::TagVal tvalue;
287 0 : tvalue.val = value;
288 0 : tags->insert(make_pair(name, tvalue));
289 0 : }
290 0 : }
291 :
292 0 : void PushStructuredSyslogStats(SyslogParser::syslog_m_t v, const std::string &stat_attr_name,
293 : StatWalker *stat_walker, std::vector<std::string> tagged_fields) {
294 : // At the top level the stat walker already has the tags so
295 : // we need to skip going through the elemental types and
296 : // creating the tag and attribute maps. At lower levels,
297 : // only strings are inserted into the tag map
298 0 : bool top_level(stat_attr_name.empty());
299 0 : DbHandler::AttribMap attribs;
300 0 : StatWalker::TagMap tags;
301 :
302 0 : if (!top_level) {
303 :
304 0 : int i = 0;
305 0 : while (!v.empty()) {
306 : /*
307 : All the key-value pairs in v will be iterated over and pushed into the stattable
308 : */
309 0 : SyslogParser::Holder d = v.begin()->second;
310 0 : const std::string &key(d.key);
311 0 : bool is_tag = false;
312 0 : if (std::find(tagged_fields.begin(), tagged_fields.end(), key) != tagged_fields.end()) {
313 0 : LOG(DEBUG, "tagged field - " << key);
314 0 : is_tag = true;
315 : }
316 :
317 0 : if (d.type == SyslogParser::str_type) {
318 0 : const std::string &sval(d.s_val);
319 0 : LOG(DEBUG, i++ << " - " << key << " : " << sval << " is_tag: " << is_tag);
320 0 : DbHandler::Var svalue(sval);
321 0 : PushStructuredSyslogAttribsAndTags(&attribs, &tags, is_tag, key, svalue);
322 0 : }
323 0 : else if (d.type == SyslogParser::int_type) {
324 0 : LOG(DEBUG, i++ << " - " << key << " : " << d.i_val << " is_tag: " << is_tag);
325 0 : if (d.i_val >= 0) { /* added this condition as having -ve values was resulting in a crash */
326 0 : DbHandler::Var ivalue(static_cast<uint64_t>(d.i_val));
327 0 : PushStructuredSyslogAttribsAndTags(&attribs, &tags, is_tag, key, ivalue);
328 0 : }
329 : }
330 : else {
331 0 : LOG(ERROR, i++ << "BAD Type: ");
332 : }
333 0 : v.erase(v.begin());
334 0 : }
335 :
336 : // Push the stats at this level
337 0 : stat_walker->Push(stat_attr_name, tags, attribs);
338 :
339 : }
340 : // Perform traversal of children
341 : else {
342 0 : PushStructuredSyslogStats(v, "data", stat_walker, tagged_fields);
343 : }
344 :
345 : // Pop the stats at this level
346 0 : if (!top_level) {
347 0 : stat_walker->Pop();
348 : }
349 0 : }
350 :
351 0 : void PushStructuredSyslogTopLevelTags(SyslogParser::syslog_m_t v, StatWalker::TagMap *top_tags) {
352 0 : StatWalker::TagVal tvalue;
353 0 : const std::string ip(SyslogParser::GetMapVals(v, "ip", ""));
354 0 : const std::string saddr(SyslogParser::GetMapVals(v, "hostname", ip));
355 0 : tvalue.val = saddr;
356 0 : top_tags->insert(make_pair("Source", tvalue));
357 0 : }
358 :
359 0 : void StructuredSyslogPush(SyslogParser::syslog_m_t v, StatWalker::StatTableInsertFn stat_db_callback,
360 : std::vector<std::string> tagged_fields) {
361 0 : StatWalker::TagMap top_tags;
362 0 : PushStructuredSyslogTopLevelTags(v, &top_tags);
363 0 : StatWalker stat_walker(stat_db_callback, (uint64_t)SyslogParser::GetMapVal (v, "timestamp", 0),
364 0 : "JunosSyslog", top_tags);
365 0 : PushStructuredSyslogStats(v, std::string(), &stat_walker, tagged_fields);
366 0 : }
367 :
368 : boost::shared_ptr<std::string>
369 0 : StructuredSyslogJsonMessage(SyslogParser::syslog_m_t v) {
370 0 : contrail_rapidjson::Document doc;
371 0 : doc.SetObject();
372 0 : for (std::map<std::string, SyslogParser::Holder>::iterator i=v.begin(); i!=v.end(); ++i) {
373 0 : SyslogParser::Holder val = i->second;
374 0 : const std::string &key(val.key);
375 0 : if (val.type == SyslogParser::str_type) {
376 0 : contrail_rapidjson::Value vk;
377 0 : contrail_rapidjson::Value value(contrail_rapidjson::kStringType);
378 0 : value.SetString(val.s_val.c_str(), doc.GetAllocator());
379 0 : doc.AddMember(vk.SetString(key.c_str(),
380 : doc.GetAllocator()), value, doc.GetAllocator());
381 0 : }
382 0 : else if (val.type == SyslogParser::int_type) {
383 0 : contrail_rapidjson::Value vk;
384 0 : contrail_rapidjson::Value value(contrail_rapidjson::kNumberType);
385 0 : value.SetUint64(val.i_val);
386 0 : doc.AddMember(vk.SetString(key.c_str(),
387 : doc.GetAllocator()), value, doc.GetAllocator());
388 0 : }
389 0 : }
390 0 : contrail_rapidjson::StringBuffer buffer;
391 0 : contrail_rapidjson::Writer<contrail_rapidjson::StringBuffer> writer(buffer);
392 0 : doc.Accept(writer);
393 0 : boost::shared_ptr<std::string> json_msg(new std::string(buffer.GetString()));
394 0 : return json_msg;
395 0 : }
396 :
397 : //Identify the prefix and return the VPN name if nothing matches then return routing_instance
398 0 : const std::string get_VPNName(const std::string &routing_instance){
399 0 : if (routing_instance.size() > 16 && (routing_instance.compare(0, 16, "Default-reverse-") == 0)){
400 0 : if (routing_instance.size() > 20 && (routing_instance.compare(16, 4, "hub-") == 0)){
401 0 : return routing_instance.substr(20, (routing_instance.size() - 20));
402 : }
403 0 : return routing_instance.substr(16, (routing_instance.size() - 16));
404 : }
405 0 : if (routing_instance.size() > 8 && (routing_instance.compare(0, 8,"Default-") == 0)){
406 0 : if (routing_instance.size() > 12 && (routing_instance.compare(8, 4, "hub-") == 0)){
407 0 : return routing_instance.substr(12, (routing_instance.size() - 12));
408 : }
409 0 : return routing_instance.substr(8, (routing_instance.size() - 8));
410 : }
411 0 : if (routing_instance.size() > 5 && (routing_instance.compare(0, 5, "mpls-") == 0)){
412 0 : if (routing_instance.size() > 9 && (routing_instance.compare(5, 4, "hub-") == 0)){
413 0 : return routing_instance.substr(9, (routing_instance.size() - 9));
414 : }
415 0 : return routing_instance.substr(5, (routing_instance.size() - 5));
416 : }
417 0 : if (routing_instance.size() > 9 && ( routing_instance.compare(0, 9, "internet-") == 0)){
418 0 : if (routing_instance.size() > 13 && (routing_instance.compare(9, 4, "hub-") == 0)){
419 0 : return routing_instance.substr(13, (routing_instance.size() - 13));
420 : }
421 0 : return routing_instance.substr(9, (routing_instance.size() - 9));
422 : }
423 0 : return routing_instance;
424 : }
425 :
426 : //Identify the VPN name from department depending upon the case
427 : // in which network segmentation is enabled or disabled.
428 0 : const std::string get_VPNName(const std::string &department,
429 : const std::string &network_segmentation,
430 : const std::string &tenant_name) {
431 0 : std::string vpn_name = department;
432 0 : if (boost::iequals(network_segmentation, "Disabled") || boost::iequals(department, "Default")) {
433 0 : vpn_name = tenant_name + "_DefaultVPN";
434 : }
435 0 : return vpn_name;
436 0 : }
437 :
438 :
439 0 : void StructuredSyslogUVESummarizeData(SyslogParser::syslog_m_t v, bool summarize_user, StructuredSyslogConfig *config_obj) {
440 0 : SDWANMetricsRecord sdwanmetricrecord;
441 0 : SDWANTenantMetricsRecord sdwantenantmetricrecord;
442 0 : SDWANKPIMetricsRecord sdwankpimetricrecord_source;
443 :
444 0 : const std::string tag(SyslogParser::GetMapVals(v, "tag", "UNKNOWN"));
445 0 : const std::string process_vol_update(SyslogParser::GetMapVals(v, "process-vol-update", "False"));
446 : // process_vol_update as True enables diff calculation
447 : // from cumulative counters across sequence of traffic syslogs.
448 : // Note that VOL_UPDATE should be considered for counters with SLA-PROFILE
449 : // or TRAFFIC-TYPE because the VOL_UPDATE doesn't contain such information.
450 0 : LOG(DEBUG, "StructuredSyslogUVESummarizeData - process-vol-update : " << process_vol_update);
451 0 : bool is_close = boost::equals(tag, "APPTRACK_SESSION_CLOSE");
452 0 : bool is_vol_update = boost::equals(tag, "APPTRACK_SESSION_VOL_UPDATE");
453 :
454 0 : if (!boost::iequals(process_vol_update, "True")) {
455 : /*
456 : For certain sites VOL_UPDATE syslog may not supported.
457 : For such sites only SESSION_CLOSE syslog should be used.
458 : */
459 0 : if (is_vol_update) {
460 : // reject vol_update syslogs.
461 0 : LOG(DEBUG, "StructuredSyslogUVESummarizeData - VOL_UPDATE msg rejected.");
462 0 : return;
463 : }
464 : }
465 :
466 :
467 0 : const std::string location(SyslogParser::GetMapVals(v, "location", "UNKNOWN"));
468 0 : const std::string tenant(SyslogParser::GetMapVals(v, "tenant", "UNKNOWN"));
469 0 : std::string sla_profile(SyslogParser::GetMapVals(v, "sla-profile", "UNKNOWN"));
470 0 : const std::string app_category(SyslogParser::GetMapVals(v, "app-category", "UNKNOWN"));
471 0 : const std::string department(SyslogParser::GetMapVals(v, "source-zone-name", "UNKNOWN"));
472 0 : const std::string dest_zone(SyslogParser::GetMapVals(v, "destination-zone-name", "UNKNOWN"));
473 0 : const std::string device_id(SyslogParser::GetMapVals(v, "device", "UNKNOWN"));
474 0 : const std::string region(SyslogParser::GetMapVals(v, "region", "DEFAULT"));
475 0 : const std::string opco(SyslogParser::GetMapVals(v, "OPCO", "DEFAULT"));
476 0 : const std::string hubs_interfaces(SyslogParser::GetMapVals(v, "HUBS", "UNKNOWN"));
477 0 : const std::string uvename = tenant + "::" + location + "::" + device_id;
478 0 : const std::string tenantuvename = region + "::" + opco + "::" + tenant;
479 0 : const std::string kpi_uvename_source = location;
480 0 : std::string traffic_type(SyslogParser::GetMapVals(v, "active-probe-params", "UNKNOWN"));
481 0 : const std::string dscp_alias_code(SyslogParser::GetMapVals(v, "dscp-alias-code", "UNKNOWN"));
482 0 : const std::string dscp_value(SyslogParser::GetMapVals(v, "dscp-value", "UNKNOWN"));
483 0 : std::string nested_appname(SyslogParser::GetMapVals(v, "nested-application", "UNKNOWN"));
484 0 : std::string service_name(SyslogParser::GetMapVals(v, "service-name", "UNKNOWN"));
485 0 : std::string appname(SyslogParser::GetMapVals(v, "application", "UNKNOWN"));
486 0 : const std::string tenant_name(SyslogParser::GetMapVals(v, "tenantaddr", "UNKNOWN"));
487 0 : const std::string network_segmentation(SyslogParser::GetMapVals(v, "network-segmentation", "UNKNOWN"));
488 0 : bool is_site_traffic_destination = true;
489 :
490 : //counters for cumulative to differential value conversation
491 0 : int64_t prev_total_bytes=0, prev_bytes_from_client=0,
492 0 : prev_bytes_from_server=0, prev_packets_from_client=0,
493 0 : prev_packets_from_server=0;
494 0 : bool process_curr_counter = true;
495 :
496 0 : if (boost::iequals(process_vol_update, "True")) {
497 : // ToDo: Remove this once vol-update syslog provides sla-profile.
498 0 : sla_profile = "DEFAULT";
499 : // ToDo: Remove this once vol-update syslog provides traffic-type.
500 0 : traffic_type = "DEFAULT";
501 : }
502 :
503 : /*
504 : If VOL_UPDATE syslogs were processed, compute diff values
505 : from cumulative traffic counters for each session-id.
506 : Note that prev counters for the session has to be checked in all cases
507 : to handle shift from
508 : cumulative -> diff computation (in case of process vol-update)
509 : to just diff computation (in case of session-close only).
510 : */
511 0 : const std::string session_id_32(SyslogParser::GetMapVals(v, "session-id-32", "-1"));
512 0 : const std::string session_unique_key = uvename + "::" + session_id_32;
513 0 : std::map<std::string, uint64_t> session_prev_traffic_counters;
514 : bool found_session_prev_counters =
515 0 : config_obj->FetchSyslogSessionCounters(session_unique_key,
516 : session_prev_traffic_counters);
517 0 : if (found_session_prev_counters) {
518 : // read previous counters
519 0 : prev_total_bytes = session_prev_traffic_counters["total-bytes"];
520 0 : prev_bytes_from_client = session_prev_traffic_counters["bytes-from-client"];
521 0 : prev_bytes_from_server = session_prev_traffic_counters["bytes-from-server"];
522 0 : prev_packets_from_server = session_prev_traffic_counters["packets-from-server"];
523 0 : prev_packets_from_client = session_prev_traffic_counters["packets-from-client"];
524 :
525 : // update & process the counter which are new and greater than before.
526 0 : if ((prev_total_bytes > SyslogParser::GetMapVal(v, "total-bytes", 0)) ||
527 0 : (prev_packets_from_client > SyslogParser::GetMapVal(v, "packets-from-client", 0))) {
528 0 : process_curr_counter = false;
529 0 : LOG(ERROR, "Syslog Session Counter is OLD !. Discarding ...");
530 : }
531 :
532 0 : if (is_close) {
533 : // session is closed.
534 : // Remove session counters from syslog session counter map.
535 : int removed_sess_counter =
536 0 : config_obj->RemoveSyslogSessionCounter(session_unique_key);
537 0 : if (removed_sess_counter == 0) {
538 0 : LOG(ERROR, "Syslog Session Counter NOT removed for key " << session_unique_key);
539 : }
540 : }
541 : }
542 :
543 : // either this is a new session,
544 : // or this update has new cumulative counter count.
545 : // add/update counters to syslog session counter map if
546 : // processing vol update is enabled.
547 0 : if (!is_close && boost::iequals(process_vol_update, "True")) {
548 0 : if (process_curr_counter) {
549 0 : std::map<std::string, uint64_t> session_curr_traffic_counters;
550 0 : session_curr_traffic_counters["total-bytes"] = SyslogParser::GetMapVal(v, "total-bytes", 0);
551 0 : session_curr_traffic_counters["bytes-from-client"] = SyslogParser::GetMapVal(v, "bytes-from-client", 0);
552 0 : session_curr_traffic_counters["bytes-from-server"] = SyslogParser::GetMapVal(v, "bytes-from-server", 0);
553 0 : session_curr_traffic_counters["packets-from-server"] = SyslogParser::GetMapVal(v, "packets-from-server", 0);
554 0 : session_curr_traffic_counters["packets-from-client"] = SyslogParser::GetMapVal(v, "packets-from-client", 0);
555 0 : bool addSessionCounter = config_obj->AddSyslogSessionCounter(session_unique_key, session_curr_traffic_counters);
556 0 : if (!addSessionCounter) {
557 0 : LOG(ERROR, "StructuredSyslogUVESummarizeData - Syslog message rejected.");
558 0 : return;
559 : }
560 :
561 0 : }
562 : }
563 :
564 :
565 : // compute diff counters
566 : //LOG(DEBUG, "prev-total-bytes: " << prev_total_bytes);
567 0 : int64_t diff_total_bytes=0, diff_bytes_from_client=0,
568 0 : diff_bytes_from_server=0, diff_packets_from_server=0,
569 0 : diff_packets_from_client=0;
570 :
571 0 : if (process_curr_counter) {
572 0 : diff_total_bytes = SyslogParser::GetMapVal(v, "total-bytes", 0) - prev_total_bytes;
573 0 : diff_bytes_from_client = SyslogParser::GetMapVal(v, "bytes-from-client", 0) - prev_bytes_from_client;
574 0 : diff_bytes_from_server = SyslogParser::GetMapVal(v, "bytes-from-server", 0) - prev_bytes_from_server;
575 0 : diff_packets_from_server = SyslogParser::GetMapVal(v, "packets-from-server", 0) - prev_packets_from_server;
576 0 : diff_packets_from_client = SyslogParser::GetMapVal(v, "packets-from-client", 0) - prev_packets_from_client;
577 : }
578 0 : LOG(DEBUG, "Diff total-bytes: " << diff_total_bytes);
579 0 : LOG(DEBUG, "Diff bytes-from-client: " << diff_bytes_from_client);
580 0 : LOG(DEBUG, "Diff bytes-from-server: " << diff_bytes_from_server);
581 0 : LOG(DEBUG, "Diff packets-from-server: " << diff_packets_from_server);
582 0 : LOG(DEBUG, "Diff packets-from-client: " << diff_packets_from_client);
583 :
584 0 : LOG(DEBUG, "UVE: dscp-alias-code: " << dscp_alias_code);
585 0 : LOG(DEBUG, "UVE: dscp-value: " << dscp_value);
586 :
587 0 : if (boost::iequals(nested_appname, "UNKNOWN") && boost::iequals(appname, "UNKNOWN")) {
588 0 : if (!(boost::iequals(service_name, "UNKNOWN")) && !(boost::iequals(service_name, "None"))) {
589 0 : nested_appname = service_name;
590 0 : appname = service_name;
591 : }
592 : }
593 :
594 : // nested_appname@UNKNOWN, nested_appname@dscp_alias_code nested_appname@DSCP-dscp_value
595 0 : std::string dscp_key = dscp_alias_code;
596 0 : if (dscp_value == "UNKNOWN") {
597 0 : dscp_key = "UNKNOWN";
598 : }
599 0 : else if (dscp_alias_code == "UNKNOWN") {
600 0 : dscp_key = "DSCP-" + dscp_value;
601 : }
602 :
603 0 : const std::string nested_appname_with_alias_code = nested_appname + "@" + dscp_key;
604 0 : const std::string tt_app_dept_info = traffic_type + "(" + nested_appname_with_alias_code + ":" + appname
605 0 : + "/" + app_category + ")" + "::" + department + "::";
606 :
607 : //username => syslog.username or syslog.source-address
608 0 : std::string username(SyslogParser::GetMapVals(v, "username", "UNKNOWN"));
609 0 : if (boost::iequals(username, "unknown")) {
610 0 : username = SyslogParser::GetMapVals(v, "source-address", "UNKNOWN");
611 : }
612 :
613 0 : sdwanmetricrecord.set_name(uvename);
614 0 : sdwantenantmetricrecord.set_name(tenantuvename);
615 0 : sdwankpimetricrecord_source.set_name(kpi_uvename_source);
616 :
617 : //Update maps for SDWANKPI metrics record
618 0 : SDWANKPIMetrics_diff sdwankpimetricdiff;
619 0 : std::map<std::string, SDWANKPIMetrics_diff> sdwan_kpi_metrics_diff_source;
620 0 : if ((is_close || is_vol_update) && (boost::iequals(dest_zone, "trust"))) {
621 0 : const std::string routing_instance (SyslogParser::GetMapVals(v, "routing-instance", "UNKNOWN"));
622 0 : std::string vpn_name = "UNKNOWN";
623 0 : if (routing_instance != "UNKNOWN") {
624 0 : vpn_name = get_VPNName(routing_instance);
625 : }
626 : else {
627 : // this case will be true for vol_update syslogs.
628 : vpn_name =
629 0 : get_VPNName(department, network_segmentation, tenant_name);
630 : }
631 :
632 0 : const std::string destination_address (SyslogParser::GetMapVals(v, "destination-address", "UNKNOWN"));
633 0 : const std::string destination_interface_name (SyslogParser::GetMapVals(v, "destination-interface-name", "UNKNOWN"));
634 0 : if (is_close)
635 : {
636 0 : sdwankpimetricdiff.set_session_close_count(1);
637 : }
638 0 : else if (is_vol_update)
639 : {
640 0 : sdwankpimetricdiff.set_bps(diff_total_bytes);
641 : }
642 :
643 0 : std::string destination_site;
644 :
645 : //Find Network only if valid VPN name is parsed from routing instance
646 0 : if (vpn_name != routing_instance){
647 0 : std::string network_key = tenant + "::" + vpn_name;
648 0 : destination_site = config_obj->FindNetwork(destination_address, network_key, location);
649 0 : }
650 : // if VPN name == routing instance, then VPN name is not valid and assign destination site to "UNKNOWN"
651 0 : if ((vpn_name == routing_instance) || destination_site.empty() ){
652 0 : destination_site = "UNKNOWN";
653 0 : is_site_traffic_destination = false;
654 : }
655 0 : LOG(DEBUG,"destination address "<< destination_address <<" in VPN " << vpn_name <<
656 : " belongs to site : " << destination_site);
657 :
658 0 : std::string searchHubInterface = destination_interface_name + ",";
659 0 : std::size_t destination_interface_name_found = hubs_interfaces.find(searchHubInterface);
660 :
661 : // map key should be destination site for source UVE and source site for destination UVE
662 0 : std::string kpimetricdiff_key_source(destination_site);
663 0 : LOG(DEBUG,"UVE: KPI key destination : " << kpimetricdiff_key_source);
664 0 : sdwan_kpi_metrics_diff_source.insert(std::make_pair(kpimetricdiff_key_source, sdwankpimetricdiff));
665 :
666 : // If destination interface name belongs to hub_interfaces then traffic goes via HUB
667 0 : if (destination_interface_name_found != std::string::npos){
668 0 : LOG(DEBUG,"destination_interface_name "<< destination_interface_name <<" found in hubs_interfaces" );
669 :
670 0 : sdwankpimetricrecord_source.set_kpi_metrics_greater_diff(sdwan_kpi_metrics_diff_source);
671 : }
672 : else {
673 0 : LOG(DEBUG,"destination_interface_name "<< destination_interface_name <<" NOT found in hubs_interfaces" );
674 :
675 0 : sdwankpimetricrecord_source.set_kpi_metrics_lesser_diff(sdwan_kpi_metrics_diff_source);
676 : }
677 0 : }//End of Update maps for SDWANKPI metrics record
678 0 : SDWANKPIMetrics::Send(sdwankpimetricrecord_source,"ObjectCPETable");
679 :
680 0 : std::string link1, link2, link1_info, link2_info, traffic_destination_link1, traffic_destination_link2, link_type_link1, link_type_link2;
681 0 : int64_t link1_bytes = SyslogParser::GetMapVal(v, "uplink-tx-bytes", -1);
682 0 : int64_t link2_bytes = SyslogParser::GetMapVal(v, "uplink-rx-bytes", -1);
683 :
684 :
685 0 : if (link1_bytes < 0 || (boost::iequals(process_vol_update, "True"))) {
686 0 : link1_bytes = diff_bytes_from_client;
687 : }
688 0 : if (link2_bytes < 0 || (boost::iequals(process_vol_update, "True"))) {
689 0 : link2_bytes = diff_bytes_from_server;
690 : }
691 :
692 0 : if (is_close || is_vol_update) {
693 : // Fetch Interfaces for VOL_UPDATE or SESSION_CLOSE syslogs.
694 :
695 0 : link1 = (SyslogParser::GetMapVals(v, "destination-interface-name", "UNKNOWN"));
696 : //vol-update syslogs does NOT contain uplink interfaces and counters.
697 0 : if (!(boost::iequals(process_vol_update, "True"))) {
698 0 : link2 = (SyslogParser::GetMapVals(v, "uplink-incoming-interface-name", "N/A"));
699 : }
700 0 : else {link2 = "N/A";}
701 :
702 0 : std::string underlay_link1 = (SyslogParser::GetMapVals(v, "underlay-destination-interface-name", "UNKNOWN"));
703 0 : link_type_link1 = (SyslogParser::GetMapVals(v, "link-type-destination-interface-name", "UNKNOWN"));
704 0 : traffic_destination_link1 = (SyslogParser::GetMapVals(v, "traffic-destination-destination-interface-name", "UNKNOWN"));
705 0 : std::string metadata_link1 = (SyslogParser::GetMapVals(v, "metadata-destination-interface-name", "UNKNOWN"));
706 :
707 0 : if ((traffic_destination_link1 == "HUB" || traffic_destination_link1 == "EHUB")
708 0 : && (is_site_traffic_destination)) {
709 0 : traffic_destination_link1 = traffic_destination_link1 + "2S" ;
710 : }
711 0 : else if (traffic_destination_link1 == "HUB" || traffic_destination_link1 == "EHUB") {
712 0 : traffic_destination_link1 = traffic_destination_link1 + "2CBO" ;
713 : }
714 :
715 0 : link1_info = link1 + "@" + underlay_link1
716 0 : + "@" + link_type_link1 + "@" + traffic_destination_link1 + "@" + metadata_link1 ;
717 :
718 0 : if (boost::iequals(link2, "N/A")) {
719 0 : link2 = link1;
720 : //link1_bytes = SyslogParser::GetMapVal(v, "bytes-from-client", 0);
721 : //link2_bytes = SyslogParser::GetMapVal(v, "bytes-from-server", 0);
722 0 : link1_bytes = diff_bytes_from_client;
723 0 : link2_bytes = diff_bytes_from_server;
724 0 : link2_info = link1_info;
725 : }
726 : else {
727 0 : std::string underlay_link2 = (SyslogParser::GetMapVals(v, "underlay-uplink-incoming-interface-name", "UNKNOWN"));
728 0 : link_type_link2 = (SyslogParser::GetMapVals(v, "link-type-uplink-incoming-interface-name", "UNKNOWN"));
729 0 : traffic_destination_link2 = (SyslogParser::GetMapVals(v, "traffic-destination-uplink-incoming-interface-name", "UNKNOWN"));
730 0 : std::string metadata_link2 = (SyslogParser::GetMapVals(v, "metadata-uplink-incoming-interface-name", "UNKNOWN"));
731 0 : link2_info = link2 + "@" + underlay_link2
732 0 : + "@" + link_type_link2 + "@" + traffic_destination_link2 + "@" + metadata_link2 ;
733 0 : }
734 :
735 0 : LOG(DEBUG,"UVE: link1_info :" << link1_info);
736 0 : LOG(DEBUG,"UVE: link2_info :" << link2_info);
737 0 : } else {
738 : // Fetch Interfaces for RT_FLOW_NEXTHOP_CHANGE syslog.
739 :
740 0 : if (!(boost::iequals(process_vol_update, "True"))) {
741 0 : link1 = (SyslogParser::GetMapVals(v, "last-destination-interface-name", "UNKNOWN"));
742 0 : link2 = (SyslogParser::GetMapVals(v, "last-incoming-interface-name", "UNKNOWN"));
743 :
744 0 : std::string underlay_link1 = (SyslogParser::GetMapVals(v, "underlay-last-destination-interface-name", "UNKNOWN"));
745 0 : link_type_link1 = (SyslogParser::GetMapVals(v, "link-type-last-destination-interface-name", "UNKNOWN"));
746 0 : traffic_destination_link1 = (SyslogParser::GetMapVals(v, "traffic-destination-last-destination-interface-name", "UNKNOWN"));
747 0 : std::string metadata_link1 = (SyslogParser::GetMapVals(v, "metadata-last-destination-interface-name", "UNKNOWN"));
748 :
749 0 : link1_info = link1 + "@" + underlay_link1
750 0 : + "@" + link_type_link1 + "@" + traffic_destination_link1 + "@" + metadata_link1 ;
751 :
752 0 : std::string underlay_link2 = (SyslogParser::GetMapVals(v, "underlay-last-incoming-interface-name", "UNKNOWN"));
753 0 : link_type_link2 = (SyslogParser::GetMapVals(v, "link-type-last-incoming-interface-name", "UNKNOWN"));
754 0 : traffic_destination_link2 = (SyslogParser::GetMapVals(v, "traffic-destination-last-incoming-interface-name", "UNKNOWN"));
755 0 : std::string metadata_link2 = (SyslogParser::GetMapVals(v, "metadata-last-incoming-interface-name", "UNKNOWN"));
756 :
757 0 : link2_info = link2 + "@" + underlay_link2
758 0 : + "@" + link_type_link2 + "@" + traffic_destination_link2 + "@" + metadata_link2 ;
759 0 : }
760 : else {
761 0 : link1 = SyslogParser::GetMapVals(v, "destination-interface-name", "UNKNOWN");
762 0 : link2 = link1;
763 :
764 0 : std::string underlay_link1 = (SyslogParser::GetMapVals(v, "underlay-destination-interface-name", "UNKNOWN"));
765 0 : link_type_link1 = (SyslogParser::GetMapVals(v, "link-type-destination-interface-name", "UNKNOWN"));
766 0 : traffic_destination_link1 = (SyslogParser::GetMapVals(v, "traffic-destination-destination-interface-name", "UNKNOWN"));
767 0 : std::string metadata_link1 = (SyslogParser::GetMapVals(v, "metadata-destination-interface-name", "UNKNOWN"));
768 :
769 0 : link1_info = link1 + "@" + underlay_link1
770 0 : + "@" + link_type_link1 + "@" + traffic_destination_link1 + "@" + metadata_link1 ;
771 :
772 0 : link2_info = link1_info;
773 0 : }
774 :
775 0 : LOG(DEBUG,"UVE: link1_info :" << link1_info);
776 0 : LOG(DEBUG,"UVE: link2_info :" << link2_info);
777 : }
778 0 : SDWANMetrics_diff sdwanmetric;
779 0 : if (is_close || is_vol_update) {
780 : //int64_t output_pkts = SyslogParser::GetMapVal(v, "packets-from-client", 0);
781 : //int64_t input_pkts = SyslogParser::GetMapVal(v, "packets-from-server", 0);
782 0 : int64_t output_pkts = diff_packets_from_client;
783 0 : int64_t input_pkts = diff_packets_from_server;
784 0 : sdwanmetric.set_total_pkts(input_pkts + output_pkts);
785 0 : sdwanmetric.set_input_pkts(input_pkts);
786 0 : sdwanmetric.set_output_pkts(output_pkts);
787 0 : sdwanmetric.set_total_bytes(diff_total_bytes);
788 0 : sdwanmetric.set_output_bytes(diff_bytes_from_client);
789 0 : sdwanmetric.set_input_bytes(diff_bytes_from_server);
790 0 : if (is_close) {
791 0 : sdwanmetric.set_session_duration(SyslogParser::GetMapVal(v, "elapsed-time", 0));
792 0 : sdwanmetric.set_session_count(1);
793 : }
794 :
795 : // Map: app_metrics_diff_sla
796 0 : std::map<std::string, SDWANMetrics_diff> app_metrics_diff_sla;
797 0 : std::string slamap_key(tt_app_dept_info + sla_profile);
798 0 : LOG(DEBUG,"UVE: app_metrics_diff_sla key :" << slamap_key);
799 0 : app_metrics_diff_sla.insert(std::make_pair(slamap_key, sdwanmetric));
800 0 : sdwanmetricrecord.set_app_metrics_diff_sla(app_metrics_diff_sla);
801 :
802 : // Map: app_metrics_diff_user
803 0 : if (summarize_user == true) {
804 0 : std::map<std::string, SDWANMetrics_diff> app_metrics_diff_user;
805 0 : std::string usermap_key(tt_app_dept_info + username);
806 0 : LOG(DEBUG,"UVE: app_metrics_diff_user key :" << usermap_key);
807 0 : app_metrics_diff_user.insert(std::make_pair(usermap_key, sdwanmetric));
808 0 : sdwanmetricrecord.set_app_metrics_diff_user(app_metrics_diff_user);
809 0 : }
810 : //replaced the fuction to the outerloop for both session_close and rt_flow_next_hop_change syslog
811 : // // Map: tenant_metrics_diff_sla
812 : // std::map<std::string, SDWANMetrics_diff> tenant_metrics_diff_sla;
813 : // std::string tenantmetric_key(location + "::" + sla_profile + "::" + traffic_type + "@" + traffic_destination_link + "@" + link_type_link);
814 : // LOG(DEBUG,"UVE: tenant_metrics_diff_sla key :" << tenantmetric_key);
815 : // tenant_metrics_diff_sla.insert(std::make_pair(tenantmetric_key, sdwanmetric));
816 : // sdwantenantmetricrecord.set_tenant_metrics_diff_sla(tenant_metrics_diff_sla);
817 : // SDWANTenantMetrics::Send(sdwantenantmetricrecord, "ObjectCPETable");
818 0 : }
819 : // Map: app_metrics_diff_link
820 : // Map: link_metrics_diff_traffic_type
821 0 : SDWANMetrics_diff sdwanmetric1;
822 0 : SDWANMetrics_diff sdwanmetric2;
823 0 : std::map<std::string, SDWANMetrics_diff> app_metrics_diff_link;
824 0 : std::map<std::string, SDWANMetrics_diff> link_metrics_diff_traffic_type;
825 0 : if (boost::equals(link1, link2)) {
826 0 : sdwanmetric1.set_total_bytes(link1_bytes + link2_bytes);
827 0 : sdwanmetric1.set_input_bytes(link2_bytes);
828 0 : sdwanmetric1.set_output_bytes(link1_bytes);
829 0 : if (is_close) {
830 0 : sdwanmetric1.set_session_duration(SyslogParser::GetMapVal(v, "elapsed-time", 0));
831 0 : sdwanmetric1.set_session_count(1);
832 : }
833 0 : std::string linkmap_key(tt_app_dept_info + link1_info);
834 0 : std::string linkmetricmap_key(link1_info + "::" + sla_profile + "::" + traffic_type);
835 0 : LOG(DEBUG,"UVE: app_metrics_diff_link key :" << linkmap_key);
836 0 : app_metrics_diff_link.insert(std::make_pair(linkmap_key, sdwanmetric1));
837 0 : sdwanmetricrecord.set_app_metrics_diff_link(app_metrics_diff_link);
838 :
839 : // Map: tenant_metrics_diff_sla
840 0 : std::map<std::string, SDWANMetrics_diff> tenant_metrics_diff_sla;
841 0 : LOG(DEBUG,"UVE: link_metrics_*_traffic_type key :" << linkmetricmap_key);
842 0 : link_metrics_diff_traffic_type.insert(std::make_pair(linkmetricmap_key, sdwanmetric1));
843 0 : sdwanmetricrecord.set_link_metrics_diff_traffic_type(link_metrics_diff_traffic_type);
844 :
845 : // Update Map: tenant_metrics_diff_sla
846 0 : std::string tenantmetric_key(location + "::" + sla_profile +
847 0 : "::" + traffic_type +
848 0 : "@" + traffic_destination_link1 +
849 0 : "@" + link_type_link1);
850 :
851 0 : LOG(DEBUG,"UVE: tenant_metrics_diff_sla key :" << tenantmetric_key);
852 0 : tenant_metrics_diff_sla.insert(std::make_pair(tenantmetric_key, sdwanmetric1));
853 0 : sdwantenantmetricrecord.set_tenant_metrics_diff_sla(tenant_metrics_diff_sla);
854 :
855 :
856 :
857 :
858 : /*
859 : // Update maps for underlay links if needed
860 : if (!(boost::equals(link1, underlay_link1))) {
861 : std::string linkmap_key(tt_app_dept_info + underlay_link1);
862 : std::string linkmetricmap_key(underlay_link1 + "::" + sla_profile + "::" + traffic_type);
863 : LOG(DEBUG,"UVE: underlay app_metrics_diff_link key :" << linkmap_key);
864 : LOG(DEBUG,"UVE: underlay link_metrics_*_traffic_type key :" << linkmetricmap_key);
865 : app_metrics_diff_link.insert(std::make_pair(linkmap_key, sdwanmetric1));
866 : link_metrics_diff_traffic_type.insert(std::make_pair(linkmetricmap_key, sdwanmetric1));
867 : sdwanmetricrecord.set_app_metrics_diff_link(app_metrics_diff_link);
868 : sdwanmetricrecord.set_link_metrics_diff_traffic_type(link_metrics_diff_traffic_type);
869 : }
870 : */
871 0 : } else {
872 0 : sdwanmetric1.set_total_bytes(link1_bytes);
873 0 : sdwanmetric1.set_output_bytes(link1_bytes);
874 0 : sdwanmetric1.set_input_bytes(0);
875 0 : sdwanmetric2.set_total_bytes(link2_bytes);
876 0 : sdwanmetric2.set_output_bytes(0);
877 0 : sdwanmetric2.set_input_bytes(link2_bytes);
878 0 : if (is_close) {
879 0 : sdwanmetric1.set_session_duration(SyslogParser::GetMapVal(v, "elapsed-time", 0));
880 0 : sdwanmetric1.set_session_count(1);
881 0 : sdwanmetric2.set_session_duration(SyslogParser::GetMapVal(v, "elapsed-time", 0));
882 0 : sdwanmetric2.set_session_count(1);
883 : }
884 :
885 0 : std::string linkmap_key1(tt_app_dept_info + link1_info);
886 0 : std::string linkmap_key2(tt_app_dept_info + link2_info);
887 0 : LOG(DEBUG,"UVE: app_metrics_diff_link key1 :" << linkmap_key1);
888 0 : LOG(DEBUG,"UVE: app_metrics_diff_link key2 :" << linkmap_key2);
889 0 : app_metrics_diff_link.insert(std::make_pair(linkmap_key1, sdwanmetric1));
890 0 : app_metrics_diff_link.insert(std::make_pair(linkmap_key2, sdwanmetric2));
891 0 : sdwanmetricrecord.set_app_metrics_diff_link(app_metrics_diff_link);
892 :
893 0 : std::string linkmetricmap_key1(link1_info + "::" + sla_profile + "::" + traffic_type);
894 0 : std::string linkmetricmap_key2(link2_info + "::" + sla_profile + "::" + traffic_type);
895 0 : LOG(DEBUG,"UVE: link_metrics_*_traffic_type key1 :" << linkmetricmap_key1);
896 0 : LOG(DEBUG,"UVE: link_metrics_*_traffic_type key2 :" << linkmetricmap_key2);
897 0 : link_metrics_diff_traffic_type.insert(std::make_pair(linkmetricmap_key1, sdwanmetric1));
898 0 : link_metrics_diff_traffic_type.insert(std::make_pair(linkmetricmap_key2, sdwanmetric2));
899 0 : sdwanmetricrecord.set_link_metrics_diff_traffic_type(link_metrics_diff_traffic_type);
900 :
901 : // Map: tenant_metrics_diff_sla
902 0 : std::map<std::string, SDWANMetrics_diff> tenant_metrics_diff_sla;
903 0 : std::string tenantmetric_key1(location + "::" +
904 0 : sla_profile + "::" +
905 0 : traffic_type + "@" +
906 0 : traffic_destination_link1 + "@" +
907 0 : link_type_link1);
908 0 : std::string tenantmetric_key2(location + "::" +
909 0 : sla_profile + "::" +
910 0 : traffic_type + "@" +
911 0 : traffic_destination_link2 + "@" +
912 0 : link_type_link2);
913 0 : LOG(DEBUG,"UVE: tenant_metrics_diff_sla key1 :" << tenantmetric_key1);
914 0 : LOG(DEBUG,"UVE: tenant_metrics_diff_sla key2 :" << tenantmetric_key2);
915 0 : tenant_metrics_diff_sla.insert(std::make_pair(tenantmetric_key1, sdwanmetric1));
916 0 : tenant_metrics_diff_sla.insert(std::make_pair(tenantmetric_key2, sdwanmetric2));
917 0 : sdwantenantmetricrecord.set_tenant_metrics_diff_sla(tenant_metrics_diff_sla);
918 :
919 : // Update maps for underlay links if needed
920 : /*
921 : if ((!(boost::equals(link1, underlay_link1))) ||
922 : (!(boost::equals(link2, underlay_link2)))) {
923 : if (!(boost::equals(link1, underlay_link1))) {
924 : std::string linkmap_key1(tt_app_dept_info + underlay_link1);
925 : std::string linkmetricmap_key1(underlay_link1 + "::" + sla_profile + "::" + traffic_type);
926 : LOG(DEBUG,"UVE: underlay app_metrics_diff_link key1 :" << linkmap_key1);
927 : LOG(DEBUG,"UVE: underlay link_metrics_*_traffic_type key1 :" << linkmetricmap_key1);
928 : app_metrics_diff_link.insert(std::make_pair(linkmap_key1, sdwanmetric1));
929 : link_metrics_diff_traffic_type.insert(std::make_pair(linkmetricmap_key1, sdwanmetric1));
930 : }
931 : if ((!(boost::equals(link2, underlay_link2))) &&
932 : (!(boost::equals(underlay_link1, underlay_link2)))) {
933 : std::string linkmap_key2(tt_app_dept_info + underlay_link2);
934 : std::string linkmetricmap_key2(underlay_link2 + "::" + sla_profile + "::" + traffic_type);
935 : LOG(DEBUG,"UVE: underlay app_metrics_diff_link key2 :" << linkmap_key2);
936 : LOG(DEBUG,"UVE: underlay link_metrics_*_traffic_type key2 :" << linkmetricmap_key2);
937 : app_metrics_diff_link.insert(std::make_pair(linkmap_key2, sdwanmetric2));
938 : link_metrics_diff_traffic_type.insert(std::make_pair(linkmetricmap_key2, sdwanmetric2));
939 :
940 : }
941 : sdwanmetricrecord.set_app_metrics_diff_link(app_metrics_diff_link);
942 : sdwanmetricrecord.set_link_metrics_diff_traffic_type(link_metrics_diff_traffic_type);
943 : }
944 : */
945 0 : }
946 :
947 0 : SDWANMetrics::Send(sdwanmetricrecord, "ObjectCPETable");
948 0 : SDWANTenantMetrics::Send(sdwantenantmetricrecord, "ObjectCPETable");
949 :
950 0 : return;
951 0 : }
952 :
953 :
954 0 : double calculate_link_score(int64_t latency, int64_t packet_loss, int64_t jitter,
955 : int64_t effective_latency_threshold, int64_t latency_factor,
956 : int64_t jitter_factor, int64_t packet_loss_factor) {
957 :
958 : double effective_latency, r_factor, mos, latency_ms, jitter_ms;
959 0 : latency_ms = latency/1000; // latency in milli secs
960 0 : jitter_ms = jitter/1000; // jitter in milli secs
961 :
962 : // Setting the default values for coefficients
963 0 : if (effective_latency_threshold == 0)
964 0 : effective_latency_threshold = 160;
965 0 : if (latency_factor == 0)
966 0 : latency_factor = 100;
967 0 : if (jitter_factor == 0)
968 0 : jitter_factor = 200;
969 0 : if (packet_loss_factor == 0)
970 0 : packet_loss_factor = 250;
971 :
972 0 : LOG(DEBUG, "Link score calculation coefficients, effective_latency_threshold : "
973 : << effective_latency_threshold
974 : << ", latency_factor : " << latency_factor
975 : << ", jitter_factor : " << jitter_factor
976 : << ", packet_loss_factor : "
977 : << packet_loss_factor);
978 :
979 : // Step-1: Calculate EffectiveLatency = (AvgLatency + 2*AvgPositiveJitter + 10)
980 0 : effective_latency =
981 0 : ((latency_ms * (latency_factor/100.0)) + ((jitter_factor/100.0)*jitter_ms) + 10);
982 : // Step-2: Calculate Intermediate R-Value
983 0 : if (effective_latency < effective_latency_threshold) {
984 0 : r_factor = 93.2 - (effective_latency/40);
985 : }
986 : else {
987 0 : r_factor = 93.2 - (effective_latency - 120)/10;
988 : }
989 : // Step-3: Adjust R-Value for PacketLoss
990 0 : r_factor = r_factor - (packet_loss * packet_loss_factor/100.0);
991 : // Step-4: Calculate MeanOpinionScore
992 0 : if (r_factor < 0 ){
993 0 : mos = 1;
994 : }
995 0 : else if ((r_factor > 0) && (r_factor < 100)) {
996 0 : mos = 1 + (0.035) * r_factor + (0.000007) * r_factor * (r_factor - 60) * (100 - r_factor);
997 : }
998 : else {
999 0 : mos = 4.5;
1000 : }
1001 0 : LOG(DEBUG, "Calculated Mean Opinion Score (link_score) for sla params is : " << mos);
1002 0 : return (mos * 20);
1003 : }
1004 :
1005 :
1006 0 : void StructuredSyslogUVESummarizeAppQoePSMR(SyslogParser::syslog_m_t v, bool summarize_user) {
1007 0 : SDWANMetricsRecord sdwanmetricrecord;
1008 0 : SDWANTenantMetricsRecord sdwantenantmetricrecord;
1009 0 : const std::string location(SyslogParser::GetMapVals(v, "location", "UNKNOWN"));
1010 0 : const std::string tenant(SyslogParser::GetMapVals(v, "tenant", "UNKNOWN"));
1011 0 : const std::string link(SyslogParser::GetMapVals(v, "destination-interface-name", "UNKNOWN"));
1012 0 : const std::string sla_profile(SyslogParser::GetMapVals(v, "sla-profile", "UNKNOWN"));
1013 0 : const std::string app_category(SyslogParser::GetMapVals(v, "app-category", "UNKNOWN"));
1014 0 : const std::string department(SyslogParser::GetMapVals(v, "source-zone-name", "UNKNOWN"));
1015 0 : const std::string device_id(SyslogParser::GetMapVals(v, "device", "UNKNOWN"));
1016 0 : const std::string region(SyslogParser::GetMapVals(v, "region", "DEFAULT"));
1017 0 : const std::string opco(SyslogParser::GetMapVals(v, "OPCO", "DEFAULT"));
1018 0 : const std::string uvename = tenant + "::" + location + "::" + device_id;
1019 0 : const std::string tenantuvename = region + "::" + opco + "::" + tenant;
1020 0 : const std::string traffic_type(SyslogParser::GetMapVals(v, "active-probe-params", "UNKNOWN"));
1021 0 : const std::string ip_dscp(SyslogParser::GetMapVals(v, "ip-dscp", "UNKNOWN"));
1022 0 : const std::string dscp_alias_code(SyslogParser::GetMapVals(v, "dscp-alias-code", "UNKNOWN"));
1023 0 : std::string nested_appname(SyslogParser::GetMapVals(v, "nested-application", "UNKNOWN"));
1024 0 : std::string service_name(SyslogParser::GetMapVals(v, "service-name", "UNKNOWN"));
1025 0 : std::string appname(SyslogParser::GetMapVals(v, "application", "UNKNOWN"));
1026 :
1027 0 : const std::string underlay_link = (SyslogParser::GetMapVals(v, "underlay-destination-interface-name", "UNKNOWN"));
1028 0 : const std::string link_type_link = (SyslogParser::GetMapVals(v, "link-type-destination-interface-name", "UNKNOWN"));
1029 0 : const std::string traffic_destination_link = (SyslogParser::GetMapVals(v, "traffic-destination-destination-interface-name", "UNKNOWN"));
1030 0 : const std::string metadata_link = (SyslogParser::GetMapVals(v, "metadata-destination-interface-name", "UNKNOWN"));
1031 0 : const std::string link_info = link + "@" + underlay_link
1032 0 : + "@" + link_type_link + "@" + traffic_destination_link + "@" + metadata_link ;
1033 :
1034 0 : LOG(DEBUG,"UVE: dscp-alias-code: " << dscp_alias_code);
1035 0 : LOG(DEBUG,"UVE: ip-dscp: " << ip_dscp);
1036 :
1037 0 : if (boost::iequals(nested_appname, "UNKNOWN") && boost::iequals(appname, "UNKNOWN")) {
1038 0 : if (!(boost::iequals(service_name, "UNKNOWN")) && !(boost::iequals(service_name, "None"))) {
1039 0 : nested_appname = service_name;
1040 0 : appname = service_name;
1041 : }
1042 : }
1043 :
1044 : // nested_appname@UNKNOWN, nested_appname@dscp_alias_code nested_appname@DSCP-dscp_value
1045 0 : std::string dscp_key = "DSCP-" + dscp_alias_code;
1046 0 : if (ip_dscp == "UNKNOWN") {
1047 0 : dscp_key = "UNKNOWN";
1048 : }
1049 0 : else if (dscp_alias_code == "UNKNOWN") {
1050 0 : dscp_key = "DSCP-" + ip_dscp;
1051 : }
1052 :
1053 0 : const std::string nested_appname_with_alias_code = nested_appname + "@" + dscp_key;
1054 :
1055 0 : const std::string tt_app_dept_info = traffic_type + "(" + nested_appname_with_alias_code + ":" + appname
1056 0 : + "/" + app_category + ")" + "::" + department + "::";
1057 :
1058 : //username => syslog.username or syslog.source-address
1059 0 : std::string username(SyslogParser::GetMapVals(v, "username", "UNKNOWN"));
1060 0 : if (boost::iequals(username, "unknown")) {
1061 0 : username = SyslogParser::GetMapVals(v, "source-address", "UNKNOWN");
1062 : }
1063 0 : sdwanmetricrecord.set_name(uvename);
1064 0 : sdwantenantmetricrecord.set_name(tenantuvename);
1065 0 : SDWANMetrics_dial sdwanmetric;
1066 0 : int64_t pkt_loss = SyslogParser::GetMapVal(v, "pkt-loss", -1);
1067 0 : int64_t rtt = SyslogParser::GetMapVal(v, "rtt", -1);
1068 0 : int64_t rtt_jitter = SyslogParser::GetMapVal(v, "rtt-jitter", -1);
1069 0 : int64_t egress_jitter = SyslogParser::GetMapVal(v, "egress-jitter", -1);
1070 0 : int64_t ingress_jitter = SyslogParser::GetMapVal(v, "ingress-jitter", -1);
1071 :
1072 : /*
1073 : Device sends high values for SLA parameters in syslog
1074 : when probe is not successfull or for some reason
1075 : device is not able to calculate SLA parameters.
1076 : High values for -
1077 : rtt -> 4294967295
1078 : rtt_jitter -> 4294967295
1079 : pkt_loss -> 255
1080 : These high values should NOT be used for calculation and
1081 : should be avoided.
1082 : */
1083 0 : if (rtt != -1 && rtt != 4294967295) {
1084 0 : sdwanmetric.set_rtt(rtt);
1085 : }
1086 0 : if (rtt_jitter != -1 && rtt_jitter != 4294967295) {
1087 0 : sdwanmetric.set_rtt_jitter(rtt_jitter);
1088 : }
1089 0 : if (egress_jitter != -1 && egress_jitter != 4294967295) {
1090 0 : sdwanmetric.set_egress_jitter(egress_jitter);
1091 : }
1092 0 : if (ingress_jitter != -1 && ingress_jitter != 4294967295) {
1093 0 : sdwanmetric.set_ingress_jitter(ingress_jitter);
1094 : }
1095 0 : if (pkt_loss != -1 && pkt_loss != 255) {
1096 : // this check is added to correct the cases in which device sends
1097 : // incorrect values containing loss% to be more than 100.
1098 0 : if (pkt_loss > 100) {
1099 0 : pkt_loss = 100;
1100 : }
1101 0 : sdwanmetric.set_pkt_loss(pkt_loss);
1102 : }
1103 0 : if ((rtt != -1) && (rtt != 4294967295) &&
1104 0 : (rtt_jitter != -1) && (rtt_jitter != 4294967295) &&
1105 0 : (pkt_loss != -1) && (pkt_loss != 255)) {
1106 0 : sdwanmetric.set_score((int64_t)calculate_link_score(rtt/2, pkt_loss, rtt_jitter,
1107 : SyslogParser::GetMapVal(v, "effective-latency-threshold",0),
1108 : SyslogParser::GetMapVal(v, "latency-factor",0),
1109 : SyslogParser::GetMapVal(v, "jitter-factor",0),
1110 : SyslogParser::GetMapVal(v, "packet-loss-factor",0) ));
1111 : }
1112 :
1113 : // Map: app_metrics_dial_sla
1114 0 : std::map<std::string, SDWANMetrics_dial> app_metrics_dial_sla;
1115 0 : std::string slamap_key(tt_app_dept_info + sla_profile);
1116 0 : LOG(DEBUG,"UVE: app_metrics_dial_sla key :" << slamap_key);
1117 0 : app_metrics_dial_sla.insert(std::make_pair(slamap_key, sdwanmetric));
1118 0 : sdwanmetricrecord.set_app_metrics_dial_sla(app_metrics_dial_sla);
1119 :
1120 : // Map: app_metrics_dial_user
1121 0 : if (summarize_user == true) {
1122 0 : std::map<std::string, SDWANMetrics_dial> app_metrics_dial_user;
1123 0 : std::string usermap_key(tt_app_dept_info + username);
1124 0 : LOG(DEBUG,"UVE: app_metrics_dial_user key :" << usermap_key);
1125 0 : app_metrics_dial_user.insert(std::make_pair(usermap_key, sdwanmetric));
1126 0 : sdwanmetricrecord.set_app_metrics_dial_user(app_metrics_dial_user);
1127 0 : }
1128 : // Map: app_metrics_dial_link
1129 0 : std::map<std::string, SDWANMetrics_dial> app_metrics_dial_link;
1130 0 : std::string linkmap_key(tt_app_dept_info + link_info);
1131 0 : LOG(DEBUG,"UVE: app_metrics_dial_link key :" << linkmap_key);
1132 0 : app_metrics_dial_link.insert(std::make_pair(linkmap_key, sdwanmetric));
1133 0 : sdwanmetricrecord.set_app_metrics_dial_link(app_metrics_dial_link);
1134 :
1135 : // Map: link_metrics_dial_traffic_type
1136 0 : std::map<std::string, SDWANMetrics_dial> link_metrics_dial_traffic_type;
1137 0 : std::string linkmetric_key(link_info + "::" + sla_profile + "::" + traffic_type);
1138 0 : LOG(DEBUG,"UVE: link_metrics_dial_traffic_type key :" << linkmetric_key);
1139 0 : link_metrics_dial_traffic_type.insert(std::make_pair(linkmetric_key, sdwanmetric));
1140 0 : sdwanmetricrecord.set_link_metrics_dial_traffic_type(link_metrics_dial_traffic_type);
1141 :
1142 : // Map: tenant_metrics_dial_sla
1143 0 : std::map<std::string, SDWANMetrics_dial> tenant_metrics_dial_sla;
1144 0 : std::string tenantmetric_key(location + "::" + sla_profile + "::" + traffic_type);
1145 0 : LOG(DEBUG,"UVE: tenant_metrics_dial_sla key :" << tenantmetric_key);
1146 0 : tenant_metrics_dial_sla.insert(std::make_pair(tenantmetric_key, sdwanmetric));
1147 0 : sdwantenantmetricrecord.set_tenant_metrics_dial_sla(tenant_metrics_dial_sla);
1148 :
1149 0 : SDWANTenantMetrics::Send(sdwantenantmetricrecord, "ObjectCPETable");
1150 0 : SDWANMetrics::Send(sdwanmetricrecord, "ObjectCPETable");
1151 0 : return;
1152 0 : }
1153 :
1154 0 : void StructuredSyslogUVESummarizeAppQoeBPS(SyslogParser::syslog_m_t v, bool summarize_user) {
1155 0 : SDWANMetricsRecord sdwanmetricrecord;
1156 0 : SDWANTenantMetricsRecord sdwantenantmetricrecord;
1157 0 : const std::string location(SyslogParser::GetMapVals(v, "location", "UNKNOWN"));
1158 0 : const std::string tenant(SyslogParser::GetMapVals(v, "tenant", "UNKNOWN"));
1159 0 : const std::string link(SyslogParser::GetMapVals(v, "previous-interface", "UNKNOWN"));
1160 0 : const std::string sla_profile(SyslogParser::GetMapVals(v, "sla-profile", "UNKNOWN"));
1161 0 : const std::string app_category(SyslogParser::GetMapVals(v, "app-category", "UNKNOWN"));
1162 0 : const std::string department(SyslogParser::GetMapVals(v, "source-zone-name", "UNKNOWN"));
1163 0 : const std::string device_id(SyslogParser::GetMapVals(v, "device", "UNKNOWN"));
1164 0 : const std::string region(SyslogParser::GetMapVals(v, "region", "DEFAULT"));
1165 0 : const std::string opco(SyslogParser::GetMapVals(v, "OPCO", "DEFAULT"));
1166 0 : const std::string uvename = tenant + "::" + location + "::" + device_id;
1167 0 : const std::string tenantuvename = region + "::" + opco + "::" + tenant;
1168 0 : const std::string traffic_type(SyslogParser::GetMapVals(v, "active-probe-params", "UNKNOWN"));
1169 0 : const std::string ip_dscp(SyslogParser::GetMapVals(v, "dscp-alias-code", "UNKNOWN"));
1170 0 : const std::string dscp_alias_code(SyslogParser::GetMapVals(v, "ip-dscp", "UNKNOWN"));
1171 0 : std::string nested_appname(SyslogParser::GetMapVals(v, "nested-application", "UNKNOWN"));
1172 0 : std::string service_name(SyslogParser::GetMapVals(v, "service-name", "UNKNOWN"));
1173 0 : std::string appname(SyslogParser::GetMapVals(v, "application", "UNKNOWN"));
1174 :
1175 0 : const std::string underlay_link = (SyslogParser::GetMapVals(v, "underlay-destination-interface-name", "UNKNOWN"));
1176 0 : const std::string link_type_link = (SyslogParser::GetMapVals(v, "link-type-destination-interface-name", "UNKNOWN"));
1177 0 : const std::string traffic_destination_link = (SyslogParser::GetMapVals(v, "traffic-destination-destination-interface-name", "UNKNOWN"));
1178 0 : const std::string metadata_link = (SyslogParser::GetMapVals(v, "metadata-destination-interface-name", "UNKNOWN"));
1179 0 : const std::string link_info = link + "@" + underlay_link
1180 0 : + "@" + link_type_link + "@" + traffic_destination_link + "@" + metadata_link ;
1181 :
1182 0 : LOG(DEBUG,"UVE: dscp-alias-code: " << dscp_alias_code);
1183 0 : LOG(DEBUG,"UVE: ip-dscp: " << ip_dscp);
1184 :
1185 0 : if (boost::iequals(nested_appname, "UNKNOWN") && boost::iequals(appname, "UNKNOWN")) {
1186 0 : if (!(boost::iequals(service_name, "UNKNOWN")) && !(boost::iequals(service_name, "None"))) {
1187 0 : nested_appname = service_name;
1188 0 : appname = service_name;
1189 : }
1190 : }
1191 :
1192 : // nested_appname@UNKNOWN, nested_appname@dscp_alias_code nested_appname@DSCP-dscp_value
1193 0 : std::string dscp_key = "DSCP-" + dscp_alias_code;
1194 0 : if (ip_dscp == "UNKNOWN") {
1195 0 : dscp_key = "UNKNOWN";
1196 : }
1197 0 : else if (dscp_alias_code == "UNKNOWN") {
1198 0 : dscp_key = "DSCP-" + ip_dscp;
1199 : }
1200 :
1201 0 : const std::string nested_appname_with_alias_code = nested_appname + "@" + dscp_key;
1202 :
1203 0 : const std::string tt_app_dept_info = traffic_type + "(" + nested_appname_with_alias_code + ":" + appname
1204 0 : + "/" + app_category + ")" + "::" + department + "::";
1205 0 : int64_t elapsed_time = SyslogParser::GetMapVal(v, "elapsed-time", 0);
1206 0 : const std::string reason = SyslogParser::GetMapVals(v, "reason", "UNKNOWN");
1207 : //username => syslog.username or syslog.source-address
1208 0 : std::string username(SyslogParser::GetMapVals(v, "username", "UNKNOWN"));
1209 0 : if (boost::iequals(username, "unknown")) {
1210 0 : username = SyslogParser::GetMapVals(v, "source-address", "UNKNOWN");
1211 : }
1212 0 : sdwanmetricrecord.set_name(uvename);
1213 0 : sdwantenantmetricrecord.set_name(tenantuvename);
1214 :
1215 0 : SDWANMetrics_diff sdwanmetric;
1216 0 : if ((elapsed_time > 2) && (!(boost::iequals(reason, "session close")))){
1217 0 : sdwanmetric.set_session_switch_count(1);
1218 : }
1219 :
1220 : // Map: app_metrics_diff_sla
1221 0 : std::map<std::string, SDWANMetrics_diff> app_metrics_diff_sla;
1222 0 : std::string slamap_key(tt_app_dept_info + sla_profile);
1223 0 : LOG(DEBUG,"UVE: app_metrics_diff_sla key :" << slamap_key);
1224 0 : app_metrics_diff_sla.insert(std::make_pair(slamap_key, sdwanmetric));
1225 0 : sdwanmetricrecord.set_app_metrics_diff_sla(app_metrics_diff_sla);
1226 :
1227 : // Map: app_metrics_diff_user
1228 0 : if (summarize_user == true) {
1229 0 : std::map<std::string, SDWANMetrics_diff> app_metrics_diff_user;
1230 0 : std::string usermap_key(tt_app_dept_info + username);
1231 0 : LOG(DEBUG,"UVE: app_metrics_diff_user key :" << usermap_key);
1232 0 : app_metrics_diff_user.insert(std::make_pair(usermap_key, sdwanmetric));
1233 0 : sdwanmetricrecord.set_app_metrics_diff_user(app_metrics_diff_user);
1234 0 : }
1235 :
1236 : // Map: app_metrics_diff_link
1237 0 : std::map<std::string, SDWANMetrics_diff> app_metrics_diff_link;
1238 0 : std::string linkmap_key(tt_app_dept_info + link_info);
1239 0 : LOG(DEBUG,"UVE: app_metrics_diff_link key :" << linkmap_key);
1240 0 : app_metrics_diff_link.insert(std::make_pair(linkmap_key, sdwanmetric));
1241 0 : sdwanmetricrecord.set_app_metrics_diff_link(app_metrics_diff_link);
1242 :
1243 : // Map: tenant_metrics_diff_sla
1244 0 : std::map<std::string, SDWANMetrics_diff> tenant_metrics_diff_sla;
1245 0 : std::string tenantmetric_key(location + "::" + sla_profile + "::" + traffic_type + "@" + traffic_destination_link + "@" + link_type_link);
1246 0 : LOG(DEBUG,"UVE: tenant_metrics_diff_sla key :" << tenantmetric_key);
1247 0 : tenant_metrics_diff_sla.insert(std::make_pair(tenantmetric_key, sdwanmetric));
1248 0 : sdwantenantmetricrecord.set_tenant_metrics_diff_sla(tenant_metrics_diff_sla);
1249 :
1250 : // Map: link_metrics_diff_traffic_type
1251 0 : std::map<std::string, SDWANMetrics_diff> link_metrics_diff_traffic_type;
1252 0 : std::string linkmetricmap_key(link_info + "::" + sla_profile + "::" + traffic_type);
1253 0 : LOG(DEBUG,"UVE: link_metrics_diff_traffic_type key :" << linkmetricmap_key);
1254 0 : link_metrics_diff_traffic_type.insert(std::make_pair(linkmetricmap_key, sdwanmetric));
1255 0 : sdwanmetricrecord.set_link_metrics_diff_traffic_type(link_metrics_diff_traffic_type);
1256 :
1257 0 : SDWANMetrics::Send(sdwanmetricrecord, "ObjectCPETable");
1258 0 : SDWANTenantMetrics::Send(sdwantenantmetricrecord, "ObjectCPETable");
1259 :
1260 0 : return;
1261 0 : }
1262 :
1263 0 : void StructuredSyslogUVESummarizeAppQoeSMV(SyslogParser::syslog_m_t v, bool summarize_user) {
1264 0 : SDWANMetricsRecord sdwanmetricrecord;
1265 0 : SDWANTenantMetricsRecord sdwantenantmetricrecord;
1266 0 : const std::string location(SyslogParser::GetMapVals(v, "location", "UNKNOWN"));
1267 0 : const std::string tenant(SyslogParser::GetMapVals(v, "tenant", "UNKNOWN"));
1268 0 : const std::string link(SyslogParser::GetMapVals(v, "destination-interface-name", "UNKNOWN"));
1269 0 : const std::string sla_profile(SyslogParser::GetMapVals(v, "sla-profile", "UNKNOWN"));
1270 0 : const std::string app_category(SyslogParser::GetMapVals(v, "app-category", "UNKNOWN"));
1271 0 : const std::string department(SyslogParser::GetMapVals(v, "source-zone-name", "UNKNOWN"));
1272 0 : const std::string device_id(SyslogParser::GetMapVals(v, "device", "UNKNOWN"));
1273 0 : const std::string region(SyslogParser::GetMapVals(v, "region", "DEFAULT"));
1274 0 : const std::string opco(SyslogParser::GetMapVals(v, "OPCO", "DEFAULT"));
1275 0 : const std::string uvename = tenant + "::" + location + "::" + device_id;
1276 0 : const std::string tenantuvename = region + "::" + opco + "::" + tenant;
1277 0 : const std::string traffic_type(SyslogParser::GetMapVals(v, "active-probe-params", "UNKNOWN"));
1278 0 : const std::string ip_dscp(SyslogParser::GetMapVals(v, "ip-dscp", "UNKNOWN"));
1279 0 : const std::string dscp_alias_code(SyslogParser::GetMapVals(v, "dscp-alias-code", "UNKNOWN"));
1280 0 : std::string nested_appname(SyslogParser::GetMapVals(v, "nested-application", "UNKNOWN"));
1281 0 : std::string appname(SyslogParser::GetMapVals(v, "application", "UNKNOWN"));
1282 0 : std::string service_name(SyslogParser::GetMapVals(v, "service-name", "UNKNOWN"));
1283 :
1284 0 : const std::string underlay_link = (SyslogParser::GetMapVals(v, "underlay-destination-interface-name", "UNKNOWN"));
1285 0 : const std::string link_type_link = (SyslogParser::GetMapVals(v, "link-type-destination-interface-name", "UNKNOWN"));
1286 0 : const std::string traffic_destination_link = (SyslogParser::GetMapVals(v, "traffic-destination-destination-interface-name", "UNKNOWN"));
1287 0 : const std::string metadata_link = (SyslogParser::GetMapVals(v, "metadata-destination-interface-name", "UNKNOWN"));
1288 0 : const std::string link_info = link + "@" + underlay_link
1289 0 : + "@" + link_type_link + "@" + traffic_destination_link + "@" + metadata_link ;
1290 :
1291 :
1292 0 : LOG(DEBUG,"UVE: dscp-alias-code: " << dscp_alias_code);
1293 0 : LOG(DEBUG,"UVE: ip-dscp: " << ip_dscp);
1294 :
1295 0 : if (boost::iequals(nested_appname, "UNKNOWN") && boost::iequals(appname, "UNKNOWN")) {
1296 0 : if (!(boost::iequals(service_name, "UNKNOWN")) && !(boost::iequals(service_name, "None"))) {
1297 0 : nested_appname = service_name;
1298 0 : appname = service_name;
1299 : }
1300 : }
1301 :
1302 : // nested_appname@UNKNOWN, nested_appname@dscp_alias_code nested_appname@DSCP-dscp_value
1303 0 : std::string dscp_key = "DSCP-" + dscp_alias_code;
1304 0 : if (ip_dscp == "UNKNOWN") {
1305 0 : dscp_key = "UNKNOWN";
1306 : }
1307 0 : else if (dscp_alias_code == "UNKNOWN") {
1308 0 : dscp_key = "DSCP-" + ip_dscp;
1309 : }
1310 :
1311 0 : const std::string nested_appname_with_alias_code = nested_appname + "@" + dscp_key;
1312 0 : const std::string tt_app_dept_info = traffic_type + "(" + nested_appname_with_alias_code + ":" + appname
1313 0 : + "/" + app_category + ")" + "::" + department + "::";
1314 :
1315 : //username => syslog.username or syslog.source-address
1316 0 : std::string username(SyslogParser::GetMapVals(v, "username", "UNKNOWN"));
1317 0 : if (boost::iequals(username, "unknown")) {
1318 0 : username = SyslogParser::GetMapVals(v, "source-address", "UNKNOWN");
1319 : }
1320 0 : sdwanmetricrecord.set_name(uvename);
1321 0 : sdwantenantmetricrecord.set_name(tenantuvename);
1322 :
1323 0 : SDWANMetrics_diff sdwanmetric;
1324 : //SDWANMetrics_dial sdwanmetric_dial;
1325 : //int64_t sampling_percentage = SyslogParser::GetMapVal(v, "sampling-percentage", -1);
1326 : //if (sampling_percentage != -1) {
1327 : // sdwanmetric_dial.set_sampling_percentage(sampling_percentage);
1328 : //}
1329 0 : int64_t violation_reason = SyslogParser::GetMapVal(v, "violation-reason", -1);
1330 0 : if (violation_reason > 0) {
1331 0 : sdwanmetric.set_sla_violation_count(1);
1332 0 : if (SyslogParser::GetMapVal(v, "jitter-violation-count", 0) != 0) {
1333 0 : sdwanmetric.set_jitter_violation_count(1);
1334 : }
1335 0 : if (SyslogParser::GetMapVal(v, "rtt-violation-count", 0) != 0) {
1336 0 : sdwanmetric.set_rtt_violation_count(1);
1337 : }
1338 0 : if (SyslogParser::GetMapVal(v, "pkt-loss-violation-count", 0) != 0) {
1339 0 : sdwanmetric.set_pkt_loss_violation_count(1);
1340 : }
1341 : }
1342 0 : else if (violation_reason == 0) {
1343 0 : sdwanmetric.set_sla_violation_duration(SyslogParser::GetMapVal(v, "violation-duration", 0));
1344 : }
1345 : else {
1346 0 : return;
1347 : }
1348 :
1349 : // Map: app_metrics_*_sla
1350 0 : std::map<std::string, SDWANMetrics_diff> app_metrics_diff_sla;
1351 0 : std::map<std::string, SDWANMetrics_dial> app_metrics_dial_sla;
1352 0 : std::string slamap_key(tt_app_dept_info + sla_profile);
1353 0 : LOG(DEBUG,"UVE: app_metrics_*_sla key :" << slamap_key);
1354 0 : app_metrics_diff_sla.insert(std::make_pair(slamap_key, sdwanmetric));
1355 : //app_metrics_dial_sla.insert(std::make_pair(slamap_key, sdwanmetric_dial));
1356 0 : sdwanmetricrecord.set_app_metrics_diff_sla(app_metrics_diff_sla);
1357 : //sdwanmetricrecord.set_app_metrics_dial_sla(app_metrics_dial_sla);
1358 :
1359 : // Map: app_metrics_*_user
1360 0 : if (summarize_user == true) {
1361 0 : std::map<std::string, SDWANMetrics_diff> app_metrics_diff_user;
1362 0 : std::map<std::string, SDWANMetrics_dial> app_metrics_dial_user;
1363 0 : std::string usermap_key(tt_app_dept_info + username);
1364 0 : LOG(DEBUG,"UVE: app_metrics_*_user key :" << usermap_key);
1365 0 : app_metrics_diff_user.insert(std::make_pair(usermap_key, sdwanmetric));
1366 : //app_metrics_dial_user.insert(std::make_pair(usermap_key, sdwanmetric_dial));
1367 0 : sdwanmetricrecord.set_app_metrics_diff_user(app_metrics_diff_user);
1368 0 : sdwanmetricrecord.set_app_metrics_dial_user(app_metrics_dial_user);
1369 0 : }
1370 : // Map: app_metrics_*_link
1371 0 : std::map<std::string, SDWANMetrics_diff> app_metrics_diff_link;
1372 : //std::map<std::string, SDWANMetrics_dial> app_metrics_dial_link;
1373 0 : std::string linkmap_key(tt_app_dept_info + link_info);
1374 0 : LOG(DEBUG,"UVE: app_metrics_*_link key :" << linkmap_key);
1375 0 : app_metrics_diff_link.insert(std::make_pair(linkmap_key, sdwanmetric));
1376 : //app_metrics_dial_link.insert(std::make_pair(linkmap_key, sdwanmetric_dial));
1377 0 : sdwanmetricrecord.set_app_metrics_diff_link(app_metrics_diff_link);
1378 : //sdwanmetricrecord.set_app_metrics_dial_link(app_metrics_dial_link);
1379 :
1380 : // Map: tenant_metrics_*_sla
1381 0 : std::map<std::string, SDWANMetrics_diff> tenant_metrics_diff_sla;
1382 0 : std::map<std::string, SDWANMetrics_dial> tenant_metrics_dial_sla;
1383 0 : std::string tenantmetric_key(location + "::" + sla_profile + "::" + traffic_type + "@" + traffic_destination_link + "@" + link_type_link);
1384 0 : LOG(DEBUG,"UVE: tenant_metrics_*_sla key :" << tenantmetric_key);
1385 0 : tenant_metrics_diff_sla.insert(std::make_pair(tenantmetric_key, sdwanmetric));
1386 : //tenant_metrics_dial_sla.insert(std::make_pair(tenantmetric_key, sdwanmetric_dial));
1387 0 : sdwantenantmetricrecord.set_tenant_metrics_diff_sla(tenant_metrics_diff_sla);
1388 : //sdwantenantmetricrecord.set_tenant_metrics_dial_sla(tenant_metrics_dial_sla);
1389 :
1390 : // Map: link_metrics_*_traffic_type
1391 0 : std::map<std::string, SDWANMetrics_diff> link_metrics_diff_traffic_type;
1392 0 : std::map<std::string, SDWANMetrics_dial> link_metrics_dial_traffic_type;
1393 0 : std::string linkmetricmap_key(link_info + "::" + sla_profile + "::" + traffic_type);
1394 0 : LOG(DEBUG,"UVE: link_metrics_*_traffic_type key :" << linkmetricmap_key);
1395 0 : link_metrics_diff_traffic_type.insert(std::make_pair(linkmetricmap_key, sdwanmetric));
1396 : //link_metrics_dial_traffic_type.insert(std::make_pair(linkmetricmap_key, sdwanmetric_dial));
1397 0 : sdwanmetricrecord.set_link_metrics_diff_traffic_type(link_metrics_diff_traffic_type);
1398 : //sdwanmetricrecord.set_link_metrics_dial_traffic_type(link_metrics_dial_traffic_type);
1399 :
1400 0 : SDWANMetrics::Send(sdwanmetricrecord, "ObjectCPETable");
1401 0 : SDWANTenantMetrics::Send(sdwantenantmetricrecord, "ObjectCPETable");
1402 :
1403 0 : return;
1404 0 : }
1405 :
1406 0 : void StructuredSyslogUVESummarizeAppQoeASMR(SyslogParser::syslog_m_t v, bool summarize_user) {
1407 0 : SDWANMetricsRecord sdwanmetricrecord;
1408 0 : SDWANTenantMetricsRecord sdwantenantmetricrecord;
1409 0 : const std::string location(SyslogParser::GetMapVals(v, "location", "UNKNOWN"));
1410 0 : const std::string tenant(SyslogParser::GetMapVals(v, "tenant", "UNKNOWN"));
1411 0 : const std::string link(SyslogParser::GetMapVals(v, "destination-interface-name", "UNKNOWN"));
1412 0 : const std::string sla_profile(SyslogParser::GetMapVals(v, "sla-profile", "UNKNOWN"));
1413 0 : const std::string device_id(SyslogParser::GetMapVals(v, "device", "UNKNOWN"));
1414 0 : const std::string region(SyslogParser::GetMapVals(v, "region", "DEFAULT"));
1415 0 : const std::string opco(SyslogParser::GetMapVals(v, "OPCO", "DEFAULT"));
1416 0 : const std::string uvename = tenant + "::" + location + "::" + device_id;
1417 0 : const std::string tenantuvename = region + "::" + opco + "::" + tenant;
1418 0 : const std::string traffic_type(SyslogParser::GetMapVals(v, "active-probe-params", "UNKNOWN"));
1419 0 : const std::string underlay_link = (SyslogParser::GetMapVals(v, "underlay-destination-interface-name", "UNKNOWN"));
1420 0 : const std::string link_type_link = (SyslogParser::GetMapVals(v, "link-type-destination-interface-name", "UNKNOWN"));
1421 0 : const std::string traffic_destination_link = (SyslogParser::GetMapVals(v, "traffic-destination-destination-interface-name", "UNKNOWN"));
1422 0 : const std::string metadata_link = (SyslogParser::GetMapVals(v, "metadata-destination-interface-name", "UNKNOWN"));
1423 0 : const std::string link_info = link + "@" + underlay_link
1424 0 : + "@" + link_type_link + "@" + traffic_destination_link + "@" + metadata_link ;
1425 :
1426 : // DSCP value is not collected for ASMR syslog because we dont display on the basis of APP here.
1427 :
1428 0 : sdwanmetricrecord.set_name(uvename);
1429 0 : sdwantenantmetricrecord.set_name(tenantuvename);
1430 0 : SDWANMetrics_dial sdwanmetric;
1431 0 : int64_t pkt_loss = SyslogParser::GetMapVal(v, "pkt-loss", -1);
1432 0 : int64_t rtt = SyslogParser::GetMapVal(v, "rtt", -1);
1433 0 : int64_t rtt_jitter = SyslogParser::GetMapVal(v, "rtt-jitter", -1);
1434 0 : int64_t egress_jitter = SyslogParser::GetMapVal(v, "egress-jitter", -1);
1435 0 : int64_t ingress_jitter = SyslogParser::GetMapVal(v, "ingress-jitter", -1);
1436 : /*
1437 : Device sends high values for SLA parameters in syslog
1438 : when probe is not successfull or for some reason
1439 : device is not able to calculate SLA parameters.
1440 : High values for -
1441 : rtt -> 4294967295
1442 : rtt_jitter -> 4294967295
1443 : pkt_loss -> 255
1444 : These high values should NOT be used for calculation and
1445 : should be avoided.
1446 : */
1447 0 : if (rtt != -1 && rtt != 4294967295) {
1448 0 : sdwanmetric.set_rtt(rtt);
1449 : }
1450 0 : if (rtt_jitter != -1 && rtt_jitter != 4294967295) {
1451 0 : sdwanmetric.set_rtt_jitter(rtt_jitter);
1452 : }
1453 0 : if (egress_jitter != -1 && egress_jitter != 4294967295) {
1454 0 : sdwanmetric.set_egress_jitter(egress_jitter);
1455 : }
1456 0 : if (ingress_jitter != -1 && ingress_jitter != 4294967295) {
1457 0 : sdwanmetric.set_ingress_jitter(ingress_jitter);
1458 : }
1459 0 : if (pkt_loss != -1 && pkt_loss != 255) {
1460 : // this check is added to correct the cases in which device sends
1461 : // incorrect values containing loss% to be more than 100.
1462 0 : if (pkt_loss > 100) {
1463 0 : pkt_loss = 100;
1464 : }
1465 0 : sdwanmetric.set_pkt_loss(pkt_loss);
1466 : }
1467 0 : if ((rtt != -1) && (rtt != 4294967295) &&
1468 0 : (rtt_jitter != -1) && (rtt_jitter != 4294967295) &&
1469 0 : (pkt_loss != -1) && (pkt_loss != 255)) {
1470 0 : sdwanmetric.set_score((int64_t)calculate_link_score(rtt/2, pkt_loss, rtt_jitter,
1471 : SyslogParser::GetMapVal(v, "effective-latency-threshold",0),
1472 : SyslogParser::GetMapVal(v, "latency-factor",0),
1473 : SyslogParser::GetMapVal(v, "jitter-factor",0),
1474 : SyslogParser::GetMapVal(v, "packet-loss-factor",0) ));
1475 : }
1476 : // Map: link_metrics_dial_traffic_type
1477 0 : std::map<std::string, SDWANMetrics_dial> link_metrics_dial_traffic_type;
1478 0 : std::string linkmap_key(link_info + "::" + sla_profile + "::" + traffic_type);
1479 0 : LOG(DEBUG,"UVE: link_metrics_dial_traffic_type key :" << linkmap_key);
1480 0 : link_metrics_dial_traffic_type.insert(std::make_pair(linkmap_key, sdwanmetric));
1481 0 : sdwanmetricrecord.set_link_metrics_dial_traffic_type(link_metrics_dial_traffic_type);
1482 :
1483 : // Map: tenant_metrics_dial_sla
1484 0 : std::map<std::string, SDWANMetrics_dial> tenant_metrics_dial_sla;
1485 0 : std::string tenantmetric_key(location + "::" + sla_profile + "::" + traffic_type);
1486 0 : LOG(DEBUG,"UVE: tenant_metrics_dial_sla key :" << tenantmetric_key);
1487 0 : tenant_metrics_dial_sla.insert(std::make_pair(tenantmetric_key, sdwanmetric));
1488 0 : sdwantenantmetricrecord.set_tenant_metrics_dial_sla(tenant_metrics_dial_sla);
1489 :
1490 0 : SDWANMetrics::Send(sdwanmetricrecord, "ObjectCPETable");
1491 0 : SDWANTenantMetrics::Send(sdwantenantmetricrecord, "ObjectCPETable");
1492 0 : return;
1493 0 : }
1494 :
1495 0 : void StructuredSyslogUVESummarize(SyslogParser::syslog_m_t v, bool summarize_user, StructuredSyslogConfig *config_obj) {
1496 0 : const std::string tag(SyslogParser::GetMapVals(v, "tag", "UNKNOWN"));
1497 0 : LOG(DEBUG,"UVE: Summarizing " << tag << " as UVE with flag summarize_user:" << summarize_user);
1498 0 : if (boost::equals(tag, "APPTRACK_SESSION_CLOSE")) {
1499 0 : StructuredSyslogUVESummarizeData(v, summarize_user, config_obj);
1500 : }
1501 0 : else if (boost::equals(tag, "APPTRACK_SESSION_VOL_UPDATE")) {
1502 0 : StructuredSyslogUVESummarizeData(v, summarize_user, config_obj);
1503 : }
1504 0 : else if (boost::equals(tag, "RT_FLOW_NEXTHOP_CHANGE")) {
1505 0 : StructuredSyslogUVESummarizeData(v, summarize_user, config_obj);
1506 : }
1507 0 : else if (boost::equals(tag, "APPQOE_BEST_PATH_SELECTED")) {
1508 0 : StructuredSyslogUVESummarizeAppQoeBPS(v, summarize_user);
1509 : }
1510 0 : else if (boost::equals(tag, "APPQOE_PASSIVE_SLA_METRIC_REPORT") ||
1511 0 : boost::equals(tag, "APPQOE_APP_PASSIVE_SLA_METRIC_REPORT")) {
1512 0 : StructuredSyslogUVESummarizeAppQoePSMR(v, summarize_user);
1513 : }
1514 0 : else if (boost::equals(tag, "APPQOE_ACTIVE_SLA_METRIC_REPORT")) {
1515 0 : StructuredSyslogUVESummarizeAppQoeASMR(v, summarize_user);
1516 : }
1517 0 : else if (boost::equals(tag, "APPQOE_SLA_METRIC_VIOLATION")) {
1518 0 : StructuredSyslogUVESummarizeAppQoeSMV(v, summarize_user);
1519 : }
1520 0 : }
1521 :
1522 0 : void StructuredSyslogDecorate (SyslogParser::syslog_m_t &v, StructuredSyslogConfig *config_obj,
1523 : boost::shared_ptr<std::string> msg, std::vector<std::string> int_fields) {
1524 :
1525 0 : int64_t from_client = SyslogParser::GetMapVal(v, "bytes-from-client", 0);
1526 0 : int64_t from_server = SyslogParser::GetMapVal(v, "bytes-from-server", 0);
1527 0 : size_t prev_pos = 0;
1528 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("total-bytes",
1529 0 : SyslogParser::Holder("total-bytes", (from_client + from_server))));
1530 0 : std::stringstream total_bytes;
1531 0 : total_bytes << (from_client + from_server);
1532 0 : prev_pos = DecorateMsg(msg, "total-bytes", total_bytes.str(), prev_pos);
1533 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("tenant",
1534 0 : SyslogParser::Holder("tenant", "UNKNOWN")));
1535 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("location",
1536 0 : SyslogParser::Holder("location", "UNKNOWN")));
1537 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("device",
1538 0 : SyslogParser::Holder("device", "UNKNOWN")));
1539 : /* get sla-profile from rule-name or sla-rule */
1540 : /* rule-name="r_apbr_d_ENG_p_Intent-1_s_sla-profile1" */
1541 0 : std::string sla_profile = SyslogParser::GetMapVals(v, "sla-rule", "");
1542 0 : if (sla_profile.empty()) {
1543 0 : std::string rn = SyslogParser::GetMapVals(v, "rule-name", "");
1544 0 : if (!rn.empty()) {
1545 0 : size_t start = rn.find_last_of('_');
1546 0 : if (start != string::npos) {
1547 0 : sla_profile = rn.substr(start+1);
1548 : }
1549 : else {
1550 0 : sla_profile = "DEFAULT";
1551 : }
1552 : }
1553 : else {
1554 0 : sla_profile = "DEFAULT";
1555 : }
1556 0 : }
1557 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("sla-profile",
1558 0 : SyslogParser::Holder("sla-profile", sla_profile)));
1559 0 : prev_pos = DecorateMsg(msg, "sla-profile", sla_profile, prev_pos);
1560 :
1561 0 : if (config_obj != NULL) {
1562 0 : std::string hn = SyslogParser::GetMapVals(v, "hostname", "");
1563 0 : boost::shared_ptr<HostnameRecord> hr = config_obj->GetHostnameRecord(hn);
1564 0 : if (hr != NULL) {
1565 0 : LOG(DEBUG, "StructuredSyslogDecorate hostname record: " << hn);
1566 0 : const std::string tenant = hr->tenant();
1567 0 : if (!tenant.empty()) {
1568 0 : v.erase("tenant");
1569 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("tenant",
1570 0 : SyslogParser::Holder("tenant", tenant)));
1571 0 : prev_pos = DecorateMsg(msg, "tenant", tenant, prev_pos);
1572 : }
1573 0 : const std::string location = hr->location();
1574 0 : if (!location.empty()) {
1575 0 : v.erase("location");
1576 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("location",
1577 0 : SyslogParser::Holder("location", location)));
1578 0 : prev_pos = DecorateMsg(msg, "location", location, prev_pos);
1579 : }
1580 0 : const std::string device = hr->device();
1581 0 : if (!device.empty()) {
1582 0 : v.erase("device");
1583 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("device",
1584 0 : SyslogParser::Holder("device", device)));
1585 0 : prev_pos = DecorateMsg(msg, "device", device, prev_pos);
1586 : }
1587 0 : const std::string hostname_tags = hr->tags();
1588 0 : if (!hostname_tags.empty()) {
1589 0 : ParseStructuredPart(&v, hostname_tags, int_fields, msg);
1590 : }
1591 0 : std::map< std::string, std::string > linkmap = hr->linkmap();
1592 : std::string links[4] = { "destination-interface-name", "last-incoming-interface-name",
1593 0 : "uplink-incoming-interface-name","last-destination-interface-name"};
1594 0 : for (int i = 0; i < 4; i++) {
1595 0 : std::string overlay_link(SyslogParser::GetMapVals(v, links[i], ""));
1596 0 : if (!overlay_link.empty() && !(boost::equals(overlay_link,"N/A"))) {
1597 0 : std::map< std::string, std::string >::iterator it = linkmap.find(overlay_link);
1598 0 : if (it != linkmap.end()) {
1599 : // linkmap value => underlay + "@" + link_type + "@" + traffic_destination + "@" + link_metadata ;
1600 0 : std::vector<std::string> link_data;
1601 0 : boost::split(link_data, it->second, boost::is_any_of("@"), boost::token_compress_on);
1602 0 : LOG(DEBUG, "StructuredSyslogDecorate: linkmap for " << links[i] << " : "
1603 : << overlay_link << " underlay " << link_data[0]);
1604 0 : LOG(DEBUG, "StructuredSyslogDecorate: linkmap for " << links[i] << " : "
1605 : << overlay_link << " link type " << link_data[1]);
1606 0 : LOG(DEBUG, "StructuredSyslogDecorate: linkmap for " << links[i] << " : "
1607 : << overlay_link << " traffic destination " << link_data[2]);
1608 0 : LOG(DEBUG, "StructuredSyslogDecorate: linkmap for " << links[i] << " : "
1609 : << overlay_link << " link metadata " << link_data[3]);
1610 :
1611 0 : std::string underlay_link_name = "underlay-" + links[i];
1612 0 : v.insert(std::pair<std::string, SyslogParser::Holder>(underlay_link_name,
1613 0 : SyslogParser::Holder(underlay_link_name, link_data[0])));
1614 0 : std::string link_type = "link-type-" + links[i];
1615 0 : v.insert(std::pair<std::string, SyslogParser::Holder>(link_type,
1616 0 : SyslogParser::Holder(link_type, link_data[1])));
1617 0 : std::string traffic_destination = "traffic-destination-" + links[i];
1618 0 : v.insert(std::pair<std::string, SyslogParser::Holder>(traffic_destination,
1619 0 : SyslogParser::Holder(traffic_destination, link_data[2])));
1620 0 : std::string link_metadata = "metadata-" + links[i];
1621 0 : v.insert(std::pair<std::string, SyslogParser::Holder>(link_metadata,
1622 0 : SyslogParser::Holder(link_metadata, link_data[3])));
1623 0 : }
1624 : }
1625 0 : }
1626 :
1627 : //const std::string tenant_record_default_tenant = "DEFAULT";
1628 0 : boost::shared_ptr<TenantRecord> tr = config_obj->GetTenantRecord(tenant);
1629 0 : LOG(DEBUG, "StructuredSyslogDecorate: Processing Tenant Record !!");
1630 : // if (tr == NULL) {
1631 : // tr = config_obj->GetTenantRecord(tenant_record_default_tenant);
1632 : // LOG(DEBUG, "StructuredSyslogDecorate: Tenant \"" << tenant << "\" not found. Reading \"DEFAULT\" Tenant Record !!");
1633 : // }
1634 0 : if (tr != NULL) {
1635 0 : const std::string tenantaddr = tr->tenantaddr();
1636 0 : if (!tenantaddr.empty()){
1637 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("tenantaddr",
1638 0 : SyslogParser::Holder("tenantaddr", tenantaddr)));
1639 : }
1640 :
1641 0 : const std::string tenant_tags = tr->tags();
1642 0 : if (!tenant_tags.empty()) {
1643 0 : ParseStructuredPart(&v, tenant_tags, int_fields, msg);
1644 : }
1645 :
1646 : //check if the syslog contains dscp-value(or ip-dscp) then find the corresponding alias-code
1647 0 : std::string dscp_value = SyslogParser::GetMapVals(v, "dscp-value", "");
1648 0 : std::string ip_dscp = SyslogParser::GetMapVals(v, "ip-dscp", "");
1649 0 : if (dscp_value.empty()) {
1650 0 : LOG(DEBUG, "StructuredSyslogDecorate: \"dscp-value\" field not found in syslog, reading \"ip-dscp\" instead ...");
1651 0 : dscp_value = ip_dscp;
1652 : }
1653 0 : if (!dscp_value.empty()) {
1654 0 : LOG(DEBUG, "StructuredSyslogDecorate: Finding alias-code for dscp-value " << dscp_value);
1655 : //find the internet protocol (IP) version for destination-address
1656 0 : const std::string destination_address (SyslogParser::GetMapVals(v, "destination-address", "UNKNOWN"));
1657 0 : int ip_version = 4;
1658 0 : if (destination_address != "UNKNOWN") {
1659 0 : ip_version = config_obj->get_ip_version (destination_address);
1660 : }
1661 0 : LOG(DEBUG, "StructuredSyslogDecorate: IP version for destination-address " << destination_address << " found to be IPv" << ip_version);
1662 0 : if (ip_version == 4) {
1663 0 : std::map< std::string, std::string > dscpmap_ipv4 = tr->dscpmap_ipv4();
1664 0 : std::map< std::string, std::string >::iterator it = dscpmap_ipv4.find(dscp_value);
1665 0 : if (it != dscpmap_ipv4.end()) {
1666 0 : LOG(DEBUG, "StructuredSyslogDecorate: alias-code for dscp-value: " << dscp_value << " is "
1667 : << it->second );
1668 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("dscp-alias-code",
1669 0 : SyslogParser::Holder("dscp-alias-code", it->second)));
1670 : }
1671 : else {
1672 0 : LOG(DEBUG, "StructuredSyslogDecorate: alias-code NOT found for dscp-value: " << dscp_value);
1673 : }
1674 0 : }
1675 0 : else if (ip_version == 6) {
1676 0 : std::map< std::string, std::string > dscpmap_ipv6 = tr->dscpmap_ipv6();
1677 0 : std::map< std::string, std::string >::iterator it = dscpmap_ipv6.find(dscp_value);
1678 0 : if (it != dscpmap_ipv6.end()) {
1679 0 : LOG(DEBUG, "StructuredSyslogDecorate: alias-code for dscp-value: " << dscp_value << " is "
1680 : << it->second );
1681 0 : v.insert(std::pair<std::string, SyslogParser::Holder>("dscp-alias-code",
1682 0 : SyslogParser::Holder("dscp-alias-code", it->second)));
1683 : }
1684 : else {
1685 0 : LOG(DEBUG, "StructuredSyslogDecorate: alias-code NOT found for dscp-value: " << dscp_value);
1686 : }
1687 0 : }
1688 : else {
1689 0 : LOG(ERROR, "StructuredSyslogDecorate: destination-address IP does not have any valid version. Skipping search for dscp-alias-code!");
1690 : }
1691 0 : }
1692 0 : }
1693 : else {
1694 0 : LOG(DEBUG, "StructuredSyslogDecorate: Tenant Record not found for: " << tenant);
1695 : }
1696 :
1697 :
1698 : /*
1699 : std::string an = SyslogParser::GetMapVals(v, "nested-application", "unknown");
1700 : if (boost::iequals(an, "unknown")) {
1701 : an = SyslogParser::GetMapVals(v, "application", "unknown");
1702 : }
1703 : size_t found = an.find_first_of(':');
1704 : while (found != string::npos) {
1705 : an[found] = '/';
1706 : found = an.find_first_of(':', found+1);
1707 : }
1708 : v.insert(std::pair<std::string, SyslogParser::Holder>("app-category",
1709 : SyslogParser::Holder("app-category", "UNKNOWN")));
1710 : v.insert(std::pair<std::string, SyslogParser::Holder>("app-subcategory",
1711 : SyslogParser::Holder("app-subcategory", "UNKNOWN")));
1712 : v.insert(std::pair<std::string, SyslogParser::Holder>("app-groups",
1713 : SyslogParser::Holder("app-groups", "UNKNOWN")));
1714 : v.insert(std::pair<std::string, SyslogParser::Holder>("app-risk",
1715 : SyslogParser::Holder("app-risk", "UNKNOWN")));
1716 :
1717 : boost::shared_ptr<ApplicationRecord> ar;
1718 : ar = config_obj->GetApplicationRecord(an);
1719 : if (ar == NULL) {
1720 : ar = config_obj->GetApplicationRecord("*");
1721 : }
1722 : if (ar != NULL) {
1723 : LOG(DEBUG, "StructuredSyslogDecorate application record: " << an);
1724 : const std::string app_category = ar->app_category();
1725 : if (!app_category.empty()) {
1726 : v.erase("app-category");
1727 : v.insert(std::pair<std::string, SyslogParser::Holder>("app-category",
1728 : SyslogParser::Holder("app-category", app_category)));
1729 : prev_pos = DecorateMsg(msg, "app-category", app_category, prev_pos);
1730 : }
1731 : const std::string app_subcategory = ar->app_subcategory();
1732 : if (!app_subcategory.empty()) {
1733 : v.erase("app-subcategory");
1734 : v.insert(std::pair<std::string, SyslogParser::Holder>("app-subcategory",
1735 : SyslogParser::Holder("app-subcategory", app_subcategory)));
1736 : prev_pos = DecorateMsg(msg, "app-subcategory", app_subcategory, prev_pos);
1737 : }
1738 : const std::string app_groups = ar->app_groups();
1739 : if (!app_groups.empty()) {
1740 : v.erase("app-groups");
1741 : v.insert(std::pair<std::string, SyslogParser::Holder>("app-groups",
1742 : SyslogParser::Holder("app-groups", app_groups)));
1743 : prev_pos = DecorateMsg(msg, "app-groups", app_groups, prev_pos);
1744 : }
1745 : const std::string app_risk = ar->app_risk();
1746 : if (!app_risk.empty()) {
1747 : v.erase("app-risk");
1748 : v.insert(std::pair<std::string, SyslogParser::Holder>("app-risk",
1749 : SyslogParser::Holder("app-risk", app_risk)));
1750 : prev_pos = DecorateMsg(msg, "app-risk", app_risk, prev_pos);
1751 : }
1752 : const std::string app_service_tags = ar->app_service_tags();
1753 : if (!app_service_tags.empty()) {
1754 : ParseStructuredPart(&v, app_service_tags, int_fields, msg);
1755 : }
1756 : } else {
1757 : LOG(INFO, "StructuredSyslogDecorate: Application Record not found for: " << an);
1758 : }
1759 : */
1760 0 : std::string sla_rec_name = tenant + "/" + device + "/" + sla_profile;
1761 0 : boost::shared_ptr<SlaProfileRecord> sla_rec;
1762 0 : sla_rec = config_obj->GetSlaProfileRecord(sla_rec_name);
1763 0 : if (sla_rec != NULL) {
1764 0 : LOG(DEBUG, "StructuredSyslogDecorate sla-profile record: " << sla_rec_name);
1765 0 : const std::string sla_params = sla_rec->sla_params();
1766 0 : if (!sla_params.empty()) {
1767 0 : ParseStructuredPart(&v, sla_params, int_fields, msg);
1768 : }
1769 0 : }
1770 0 : }
1771 : else {
1772 0 : LOG(DEBUG, "StructuredSyslogDecorate: Hostname Record not found for: " << hn);
1773 : }
1774 0 : }
1775 0 : }
1776 :
1777 :
1778 : /* -------Structured syslog parsing.
1779 : -------For newly received tcp message on port 3514(structured-syslog port),
1780 :
1781 : 1. Check if there is old buffer from previous message (start ptr = 0)
1782 : a. If yes,
1783 : then append newly received tcp message to old buffer, and take forward
1784 : appended message for further processing, otherwise take forward just
1785 : the received message
1786 :
1787 : 2. Identifying the start and end of the message, ( Len = received buffer length
1788 : or the appended buffer + received buffer length)
1789 : a. Find the first space (" ")
1790 : from the start, and take up the word from the start (pointer) to the space
1791 : for parsing prepended syslog message length.
1792 : b. If message length conversion doesn't turn up to be 0,
1793 : - then end pointer is pointed to message length + no. of
1794 : bytes after space and start pointer to first char after space.
1795 : c. But if message length conversion is 0, determination of start and end of
1796 : syslog message is done by parsing each byte/char of the message till either
1797 : the start and end are found or we run our of Len.
1798 : - The position of char '<' is taken as start pointer and
1799 : char ']' is taken as end pointer.
1800 :
1801 : 3. If end char of structured syslog ']' is not found upon parsing the complete
1802 : received message, the message from the start till the end of received message is
1803 : put into session buffer anticipating the remaining part of structured syslog in
1804 : next tcp buffer which will be appended to session buffer as pointedin step 1.
1805 : The necessary condition here is that the end pointer index should be either
1806 : greater than the received tcp buffer length (len, in this case we will directly
1807 : put the message into buffer) or it should point to received tcp buffer length
1808 : (len), in this case will check for last element to have end delimiter ']'. check
1809 : for following condition below in code for step 3. (((end > len) || ((end ==
1810 : len) && (*(p + end - 1) != ']') )) && (sess_buf != NULL))
1811 :
1812 : 4. If the above step (step 3) holds true, i.e. complete syslog message remains
1813 : to be be received, the process follows again from step 1. Else next step (step
1814 : 5) follows for parsing the identified structured syslog message.
1815 :
1816 : 5. The identified structured syslog message is first parsed for syslog part of
1817 : message and then structured part of syslog.
1818 :
1819 : 6. Upon parsing of syslog message in step 5, check for the remaining message in
1820 : received tcp buffer (multiple syslog messages can be in single buffer) and shift
1821 : start and end pointers as follows below.
1822 : a. Shift the start pointer to 1 + end pointer of previously parsed message,
1823 : if parsing the syslog in step 5 is unsuccessful.
1824 : b. Shift the start pointer to previous start pointer + message length of
1825 : previously parsed message, if parsing the syslog in step 5 is successful.
1826 :
1827 : 7. Check if start pointer index is equal to received tcp buffer length (meaning
1828 : the complete received tcp buffer is parsed), otherwise flow jumps to step 2 with
1829 : new (shifted) start pointer till we parse complete received tcp buffer. */
1830 :
1831 :
1832 15 : bool ProcessStructuredSyslog(const uint8_t *data, size_t len,
1833 : const boost::asio::ip::address remote_address,
1834 : StatWalker::StatTableInsertFn stat_db_callback, StructuredSyslogConfig *config_obj,
1835 : boost::shared_ptr<StructuredSyslogForwarder> forwarder, boost::shared_ptr<std::string> sess_buf) {
1836 15 : boost::system::error_code ec;
1837 15 : const std::string ip(remote_address.to_string(ec));
1838 : const uint8_t *p;
1839 15 : std::string full_log;
1840 :
1841 15 : size_t end, len_end, start = 0;
1842 : bool r;
1843 :
1844 15 : while (!*(data + len - 1))
1845 0 : --len;
1846 15 : LOG(DEBUG, "full structured_syslog: " << std::string(data + start, data + len) << " len: " << len);
1847 15 : if (sess_buf != NULL) {
1848 9 : full_log = *sess_buf + std::string(data + start, data + len);
1849 9 : p = reinterpret_cast<const uint8_t*>(full_log.data());
1850 9 : len += sess_buf->length();
1851 9 : LOG(DEBUG, "structured_syslog sess_buf + new buf: " << full_log << " len: " << len);
1852 9 : sess_buf->clear();
1853 : } else {
1854 6 : p = data;
1855 : }
1856 :
1857 : do {
1858 36 : SyslogParser::syslog_m_t v;
1859 36 : end = start + 1;
1860 36 : len_end = start + 1;
1861 186 : while ((*(p + len_end - 1) != ' ') && (len_end < len))
1862 150 : ++len_end;
1863 :
1864 : /* use prepended msg len to find the end of msg, if it exists */
1865 36 : if (len_end != len) {
1866 33 : bool is_msg_len = true;
1867 33 : int mlen_idx = start;
1868 33 : long int mlen = 0;
1869 131 : while (is_msg_len && ((p + mlen_idx) < (p + len_end - 1))) {
1870 98 : if (!(isdigit(*(p + mlen_idx)))) {is_msg_len = false;}
1871 98 : mlen_idx++;
1872 : }
1873 33 : if (is_msg_len) {
1874 24 : std::string mlenstr = std::string(p + start, p + len_end);
1875 24 : mlen = strtol(mlenstr.c_str(), NULL, 10);
1876 24 : }
1877 33 : LOG (DEBUG, "prepended message length: " << mlen);
1878 33 : if (mlen != 0) {
1879 24 : len_end += mlen;
1880 : } else {
1881 2307 : while ((*(p + len_end - 1) != ']') && (len_end < len)){
1882 : /* check for start of message if message length doesn't exist */
1883 2298 : if (*(p + end - 1 ) == '<'){
1884 7 : start = end - 1;
1885 : }
1886 2298 : ++end;
1887 2298 : ++len_end;
1888 : }
1889 : }
1890 : }
1891 36 : end = len_end;
1892 :
1893 : // check if end of tcp buffer is reached and message delimiter ']' has arrived,
1894 : // if not, wait till it comes in next tcp buffer
1895 36 : if (((end > len) ||
1896 72 : ((end == len) && (*(p + end - 1) != ']') )) && (sess_buf != NULL)) {
1897 : /* limiting session buffer to 5KB */
1898 4 : if (len-start < 5120) {
1899 4 : sess_buf->append(std::string(p + start, p + len));
1900 4 : LOG(DEBUG, "structured_syslog next sess_buf: "
1901 : << *sess_buf << " len: "<< len-start);
1902 4 : return true;
1903 : }
1904 : else {
1905 0 : LOG(ERROR, "next session buffer length too high, discarding buffer!!"
1906 : "[log msg buf truncated to 2048 bytes] next sess_buf: "
1907 : << std::string(p + start, p + 2048) << " length: "<< len-start);
1908 0 : return false;
1909 : }
1910 : }
1911 32 : r = SyslogParser::parse_syslog (p + start, p + end, v);
1912 32 : LOG(DEBUG, "structured_syslog: " << std::string(p + start, p + end) <<
1913 : " start: " << start << " end: " << end << " parsed " << r);
1914 32 : if (r) {
1915 31 : v.insert(std::pair<std::string, SyslogParser::Holder>("ip",
1916 62 : SyslogParser::Holder("ip", ip)));
1917 31 : std::stringstream lenss;
1918 31 : lenss << SyslogParser::GetMapVal(v, "msglen", 0);
1919 31 : std::string lenstr = lenss.str();
1920 31 : int message_len = SyslogParser::GetMapVal(v, "msglen", len);
1921 31 : if (message_len != (int)len) {
1922 24 : start += lenstr.length() + 1;
1923 : }
1924 31 : LOG(DEBUG, "structured_syslog message_len: " << message_len);
1925 31 : SyslogParser::PostParsing(v);
1926 31 : if (StructuredSyslogPostParsing(v, config_obj, stat_db_callback, p + start, end-start, forwarder) == false)
1927 : {
1928 31 : LOG(DEBUG, "structured_syslog not handled");
1929 : }
1930 31 : if (message_len == (int)len) {
1931 7 : start = end + 1;
1932 : } else {
1933 24 : start += message_len;
1934 : }
1935 31 : } else {
1936 1 : LOG(ERROR, "structured_syslog parse failed for: " << std::string(p + start, p + end));
1937 1 : start = end;
1938 : }
1939 219 : while (!v.empty()) {
1940 187 : v.erase(v.begin());
1941 : }
1942 68 : } while (start<len);
1943 11 : return r;
1944 15 : }
1945 :
1946 : } // namespace impl
1947 :
1948 : class StructuredSyslogServer::StructuredSyslogServerImpl {
1949 : public:
1950 0 : StructuredSyslogServerImpl(EventManager *evm, uint16_t port,
1951 : const vector<string> &structured_syslog_tcp_forward_dst,
1952 : const std::string &structured_syslog_kafka_broker,
1953 : const std::string &structured_syslog_kafka_topic,
1954 : const Options::Kafka &kafka_options,
1955 : uint16_t structured_syslog_kafka_partitions,
1956 : uint64_t structured_syslog_active_session_map_limit,
1957 : ConfigClientCollector *config_client,
1958 0 : StatWalker::StatTableInsertFn stat_db_callback) :
1959 0 : udp_server_(new StructuredSyslogUdpServer(evm, port,
1960 0 : stat_db_callback)),
1961 0 : tcp_server_(new StructuredSyslogTcpServer(evm, port,
1962 0 : stat_db_callback)),
1963 0 : structured_syslog_config_(new StructuredSyslogConfig(config_client, structured_syslog_active_session_map_limit)) {
1964 0 : if ((structured_syslog_tcp_forward_dst.size() != 0) || structured_syslog_kafka_broker != "") {
1965 0 : forwarder_.reset(new StructuredSyslogForwarder (evm, structured_syslog_tcp_forward_dst,
1966 : structured_syslog_kafka_broker,
1967 : structured_syslog_kafka_topic,
1968 : kafka_options,
1969 0 : structured_syslog_kafka_partitions));
1970 : } else {
1971 0 : LOG(DEBUG, "forward destination not configured");
1972 : }
1973 :
1974 0 : }
1975 :
1976 0 : ~StructuredSyslogServerImpl() {
1977 0 : }
1978 :
1979 0 : StructuredSyslogConfig *GetStructuredSyslogConfig() {
1980 0 : return structured_syslog_config_;
1981 : }
1982 :
1983 0 : boost::shared_ptr<StructuredSyslogForwarder> GetStructuredSyslogForwarder() {
1984 0 : return forwarder_;
1985 : }
1986 0 : bool Initialize() {
1987 0 : if (udp_server_->Initialize(GetStructuredSyslogConfig(), GetStructuredSyslogForwarder())) {
1988 0 : return tcp_server_->Initialize(GetStructuredSyslogConfig(), GetStructuredSyslogForwarder());
1989 : } else {
1990 0 : return false;
1991 : }
1992 : }
1993 :
1994 0 : void Shutdown() {
1995 0 : udp_server_->Shutdown();
1996 0 : UdpServerManager::DeleteServer(udp_server_);
1997 0 : udp_server_ = NULL;
1998 0 : tcp_server_->Shutdown();
1999 0 : TcpServerManager::DeleteServer(tcp_server_);
2000 0 : if (forwarder_ != NULL)
2001 0 : forwarder_->Shutdown();
2002 0 : }
2003 :
2004 0 : boost::asio::ip::udp::endpoint GetLocalEndpoint(
2005 : boost::system::error_code *ec) {
2006 0 : return udp_server_->GetLocalEndpoint(ec);
2007 : }
2008 :
2009 : private:
2010 : //
2011 : // StructuredSyslogUdpServer
2012 : //
2013 : class StructuredSyslogUdpServer : public UdpServer {
2014 : public:
2015 0 : StructuredSyslogUdpServer(EventManager *evm, uint16_t port,
2016 0 : StatWalker::StatTableInsertFn stat_db_callback) :
2017 : UdpServer(evm, kBufferSize),
2018 0 : port_(port),
2019 0 : stat_db_callback_(stat_db_callback) {
2020 0 : }
2021 :
2022 0 : bool Initialize(StructuredSyslogConfig *config_obj,
2023 : boost::shared_ptr<StructuredSyslogForwarder> forwarder) {
2024 0 : int count = 0;
2025 0 : while (count++ < kMaxInitRetries) {
2026 0 : if (UdpServer::Initialize(port_)) {
2027 0 : break;
2028 : }
2029 0 : sleep(1);
2030 : }
2031 0 : if (!(count < kMaxInitRetries)) {
2032 0 : LOG(ERROR, "EXITING: StructuredSyslogUdpServer initialization failed "
2033 : << "for port " << port_);
2034 0 : exit(1);
2035 : }
2036 0 : StartReceive();
2037 0 : config_obj_ = config_obj;
2038 0 : forwarder_ = forwarder;
2039 0 : return true;
2040 : }
2041 :
2042 0 : virtual void OnRead(const boost::asio::const_buffer &recv_buffer,
2043 : const boost::asio::ip::udp::endpoint &remote_endpoint) {
2044 0 : size_t recv_buffer_size(boost::asio::buffer_size(recv_buffer));
2045 0 : if (!structured_syslog::impl::ProcessStructuredSyslog(boost::asio::buffer_cast<const uint8_t *>(recv_buffer),
2046 0 : recv_buffer_size, remote_endpoint.address(), stat_db_callback_, config_obj_, forwarder_,
2047 0 : boost::shared_ptr<std::string>())) {
2048 0 : LOG(ERROR, "ProcessStructuredSyslog UDP FAILED for : " << remote_endpoint);
2049 : } else {
2050 0 : LOG(DEBUG, "ProcessStructuredSyslog UDP SUCCESS for : " << remote_endpoint);
2051 : }
2052 :
2053 0 : DeallocateBuffer(recv_buffer);
2054 0 : }
2055 :
2056 : private:
2057 :
2058 : static const int kMaxInitRetries = 5;
2059 : static const int kBufferSize = 32 * 1024;
2060 :
2061 : uint16_t port_;
2062 : StatWalker::StatTableInsertFn stat_db_callback_;
2063 : StructuredSyslogConfig *config_obj_;
2064 : boost::shared_ptr<StructuredSyslogForwarder> forwarder_;
2065 : };
2066 :
2067 : class StructuredSyslogTcpServer;
2068 :
2069 : class StructuredSyslogTcpSession : public TcpSession {
2070 : public:
2071 : typedef boost::intrusive_ptr<StructuredSyslogTcpSession> StructuredSyslogTcpSessionPtr;
2072 0 : StructuredSyslogTcpSession (StructuredSyslogTcpServer *server, Socket *socket) :
2073 0 : TcpSession(server, socket) {
2074 0 : sess_buf.reset(new std::string(""));
2075 : //set_observer(boost::bind(&SyslogTcpSession::OnEvent, this, _1, _2));
2076 0 : }
2077 0 : virtual void OnRead (const boost::asio::const_buffer buf) {
2078 0 : boost::system::error_code ec;
2079 0 : StructuredSyslogTcpServer *sserver = dynamic_cast<StructuredSyslogTcpServer *>(server());
2080 : //TODO: handle error
2081 0 : sserver->ReadMsg(StructuredSyslogTcpSessionPtr(this), buf, socket ()->remote_endpoint(ec));
2082 0 : }
2083 : boost::shared_ptr<std::string> sess_buf;
2084 : };
2085 :
2086 : //
2087 : // StructuredSyslogTcpServer
2088 : //
2089 : class StructuredSyslogTcpServer : public TcpServer {
2090 : public:
2091 : typedef boost::intrusive_ptr<StructuredSyslogTcpSession> StructuredSyslogTcpSessionPtr;
2092 0 : StructuredSyslogTcpServer(EventManager *evm, uint16_t port,
2093 0 : StatWalker::StatTableInsertFn stat_db_callback) :
2094 : TcpServer(evm),
2095 0 : port_(port),
2096 0 : session_(NULL),
2097 0 : stat_db_callback_(stat_db_callback) {
2098 0 : }
2099 :
2100 0 : virtual TcpSession *AllocSession(Socket *socket)
2101 : {
2102 0 : session_ = new StructuredSyslogTcpSession (this, socket);
2103 0 : return session_;
2104 : }
2105 :
2106 0 : bool Initialize(StructuredSyslogConfig *config_obj, boost::shared_ptr<StructuredSyslogForwarder> forwarder) {
2107 0 : TcpServer::Initialize (port_);
2108 0 : LOG(DEBUG, __func__ << " Initialization of TCP StructuredSyslog listener @" << port_);
2109 0 : config_obj_ = config_obj;
2110 0 : forwarder_ = forwarder;
2111 0 : return true;
2112 : }
2113 :
2114 0 : virtual void ReadMsg(StructuredSyslogTcpSessionPtr sess, const boost::asio::const_buffer &recv_buffer,
2115 : const boost::asio::ip::tcp::endpoint &remote_endpoint) {
2116 0 : size_t recv_buffer_size(boost::asio::buffer_size(recv_buffer));
2117 :
2118 0 : if (!structured_syslog::impl::ProcessStructuredSyslog(
2119 : boost::asio::buffer_cast<const uint8_t *>(recv_buffer),
2120 0 : recv_buffer_size, remote_endpoint.address(), stat_db_callback_, config_obj_,
2121 0 : forwarder_, sess->sess_buf)) {
2122 0 : LOG(ERROR, "ProcessStructuredSyslog TCP FAILED for : " << remote_endpoint);
2123 : } else {
2124 0 : LOG(DEBUG, "ProcessStructuredSyslog TCP SUCCESS for : " << remote_endpoint);
2125 : }
2126 :
2127 : //sess->server()->DeleteSession (sess.get());
2128 0 : sess->ReleaseBuffer(recv_buffer);
2129 0 : }
2130 :
2131 : private:
2132 : uint16_t port_;
2133 : StructuredSyslogTcpSession *session_;
2134 : StatWalker::StatTableInsertFn stat_db_callback_;
2135 : StructuredSyslogConfig *config_obj_;
2136 : boost::shared_ptr<StructuredSyslogForwarder> forwarder_;
2137 : };
2138 : StructuredSyslogUdpServer *udp_server_;
2139 : StructuredSyslogTcpServer *tcp_server_;
2140 : boost::shared_ptr<StructuredSyslogForwarder> forwarder_;
2141 : StructuredSyslogConfig *structured_syslog_config_;
2142 : };
2143 :
2144 0 : StructuredSyslogServer::StructuredSyslogServer(EventManager *evm,
2145 : uint16_t port, const vector<string> &structured_syslog_tcp_forward_dst,
2146 : const std::string &structured_syslog_kafka_broker,
2147 : const std::string &structured_syslog_kafka_topic,
2148 : uint16_t structured_syslog_kafka_partitions,
2149 : uint64_t structured_syslog_active_session_map_limit,
2150 : const Options::Kafka &kafka_options,
2151 : ConfigClientCollector *config_client,
2152 0 : StatWalker::StatTableInsertFn stat_db_fn) {
2153 0 : impl_ = new StructuredSyslogServerImpl(evm, port, structured_syslog_tcp_forward_dst,
2154 : structured_syslog_kafka_broker,
2155 : structured_syslog_kafka_topic,
2156 : kafka_options,
2157 : structured_syslog_kafka_partitions,
2158 : structured_syslog_active_session_map_limit,
2159 0 : config_client, stat_db_fn);
2160 0 : }
2161 :
2162 0 : StructuredSyslogServer::~StructuredSyslogServer() {
2163 0 : if (impl_) {
2164 0 : delete impl_;
2165 0 : impl_ = NULL;
2166 : }
2167 0 : }
2168 :
2169 0 : bool StructuredSyslogServer::Initialize() {
2170 0 : return impl_->Initialize();
2171 : }
2172 :
2173 0 : void StructuredSyslogServer::Shutdown() {
2174 0 : impl_->Shutdown();
2175 0 : }
2176 :
2177 0 : boost::asio::ip::udp::endpoint StructuredSyslogServer::GetLocalEndpoint(
2178 : boost::system::error_code *ec) {
2179 0 : return impl_->GetLocalEndpoint(ec);
2180 : }
2181 :
2182 : //
2183 : // StructuredSyslogTcpForwarderSession
2184 : //
2185 : class StructuredSyslogTcpForwarderSession : public TcpSession {
2186 : private:
2187 : StructuredSyslogTcpForwarder *server_;
2188 :
2189 : public:
2190 0 : StructuredSyslogTcpForwarderSession (StructuredSyslogTcpForwarder *server, Socket *socket) :
2191 : TcpSession((TcpServer*)server, socket),
2192 0 : server_(server){
2193 0 : }
2194 :
2195 0 : virtual void OnRead (const boost::asio::const_buffer buf) {
2196 0 : LOG(DEBUG, "StructuredSyslogTcpForwarderSession OnRead");
2197 0 : }
2198 :
2199 0 : virtual void WriteReady(const boost::system::error_code &ec) {
2200 0 : server_->WriteReady(ec);
2201 0 : }
2202 : };
2203 :
2204 0 : StructuredSyslogTcpForwarder::StructuredSyslogTcpForwarder(EventManager *evm, const std::string &ipaddress, int port) :
2205 : TcpServer(evm),
2206 0 : ipaddress_(ipaddress),
2207 0 : port_(port),
2208 0 : session_(NULL),
2209 0 : ready_to_send_(true) {
2210 0 : }
2211 :
2212 0 : TcpSession* StructuredSyslogTcpForwarder::AllocSession(Socket *socket) {
2213 0 : session_ = new StructuredSyslogTcpForwarderSession(this, socket);
2214 0 : return session_;
2215 : }
2216 :
2217 0 : void StructuredSyslogTcpForwarder::WriteReady(const boost::system::error_code &ec) {
2218 0 : LOG(DEBUG, "StructuredSyslogTcpForwarder::WriteReady");
2219 0 : if (ec) {
2220 0 : return;
2221 : }
2222 : {
2223 0 : std::scoped_lock lock(send_mutex_);
2224 0 : ready_to_send_ = true;
2225 0 : }
2226 : }
2227 :
2228 0 : void StructuredSyslogTcpForwarder::Connect() {
2229 0 : boost::system::error_code ec;
2230 0 : boost::asio::ip::tcp::endpoint endpoint;
2231 0 : endpoint.address(AddressFromString(ipaddress_, &ec));
2232 0 : endpoint.port(port_);
2233 0 : TcpServer::Connect(session_, endpoint);
2234 0 : }
2235 :
2236 0 : bool StructuredSyslogTcpForwarder::Send(const u_int8_t *data, size_t size, size_t *actual) {
2237 0 : *actual = 0;
2238 0 : std::scoped_lock lock(send_mutex_);
2239 0 : if (ready_to_send_) {
2240 0 : ready_to_send_ = session_->Send(data, size, actual);
2241 : }
2242 0 : return ready_to_send_;
2243 0 : }
2244 :
2245 0 : bool StructuredSyslogTcpForwarder::Connected() {
2246 0 : boost::system::error_code ec;
2247 0 : Endpoint remote = session_->socket()->remote_endpoint(ec);
2248 0 : return session_->Connected(remote);
2249 : }
2250 :
2251 0 : void StructuredSyslogTcpForwarder::SetSocketOptions() {
2252 0 : session_->SetSocketOptions();
2253 0 : }
2254 :
2255 0 : StructuredSyslogForwarder::StructuredSyslogForwarder(EventManager *evm,
2256 : const vector <std::string> &tcp_forward_dst,
2257 : const std::string &structured_syslog_kafka_broker,
2258 : const std::string &structured_syslog_kafka_topic,
2259 : const Options::Kafka &kafka_options,
2260 0 : uint16_t structured_syslog_kafka_partitions):
2261 0 : evm_(evm) {
2262 0 : if (tcp_forward_dst.size() != 0) {
2263 0 : tcpForwarder_poll_timer_= TimerManager::CreateTimer(*evm->io_service(),
2264 : "tcpForwarder poll timer",
2265 : TaskScheduler::GetInstance()->GetTaskId("tcpForwarder poller"));
2266 0 : tcpForwarder_poll_timer_->Start(tcpForwarderPollInterval,
2267 : boost::bind(&StructuredSyslogForwarder::PollTcpForwarder, this),
2268 : boost::bind(&StructuredSyslogForwarder::PollTcpForwarderErrorHandler, this, _1, _2));
2269 : }
2270 0 : Init(tcp_forward_dst, structured_syslog_kafka_broker, structured_syslog_kafka_topic,
2271 : kafka_options,
2272 : structured_syslog_kafka_partitions);
2273 0 : }
2274 :
2275 0 : void StructuredSyslogForwarder::Init(const std::vector<std::string> &tcp_forward_dst,
2276 : const std::string &structured_syslog_kafka_broker,
2277 : const std::string &structured_syslog_kafka_topic,
2278 : const Options::Kafka &kafka_options,
2279 : uint16_t structured_syslog_kafka_partitions) {
2280 0 : for (std::vector<std::string>::const_iterator it = tcp_forward_dst.begin(); it != tcp_forward_dst.end(); ++it) {
2281 0 : std::vector<std::string> dest;
2282 0 : boost::split(dest, *it, boost::is_any_of(":"), boost::token_compress_on);
2283 : StructuredSyslogTcpForwarder* fwder = new StructuredSyslogTcpForwarder(evm_,
2284 0 : dest[0],
2285 0 : atoi(dest[1].c_str()));
2286 0 : fwder->CreateSession();
2287 0 : fwder->Connect();
2288 0 : fwder->SetSocketOptions();
2289 0 : tcpForwarder_.push_back(fwder);
2290 0 : }
2291 0 : if (structured_syslog_kafka_broker != "") {
2292 0 : kafkaForwarder_ = new KafkaForwarder(evm_, structured_syslog_kafka_broker,
2293 : structured_syslog_kafka_topic,
2294 : kafka_options,
2295 0 : structured_syslog_kafka_partitions);
2296 : } else {
2297 0 : kafkaForwarder_ = NULL;
2298 : }
2299 0 : }
2300 :
2301 0 : StructuredSyslogForwarder::~StructuredSyslogForwarder() {
2302 0 : Shutdown();
2303 0 : if (tcpForwarder_poll_timer_) {
2304 0 : TimerManager::DeleteTimer(tcpForwarder_poll_timer_);
2305 0 : tcpForwarder_poll_timer_ = NULL;
2306 : }
2307 0 : }
2308 :
2309 0 : void StructuredSyslogForwarder::PollTcpForwarderErrorHandler(string error_name,
2310 : string error_message) {
2311 0 : LOG(ERROR, "PollTcpForwarder Timer Err: " << error_name << " " << error_message);
2312 0 : }
2313 :
2314 0 : bool StructuredSyslogForwarder::PollTcpForwarder() {
2315 0 : LOG(DEBUG, "PollTcpForwarder start");
2316 0 : for (std::vector<StructuredSyslogTcpForwarder*>::iterator it = tcpForwarder_.begin();
2317 0 : it != tcpForwarder_.end(); ++it) {
2318 0 : if ((*it)->Connected() == false) {
2319 0 : std::string dst = (*it)->GetIpAddress();
2320 0 : int port = (*it)->GetPort();
2321 0 : LOG(DEBUG,"reconnecting to remote syslog server " << dst << ":" << port);
2322 0 : StructuredSyslogTcpForwarder* old_fwder = *it;
2323 0 : StructuredSyslogTcpForwarder* new_fwder = new StructuredSyslogTcpForwarder(evm_, dst, port);
2324 0 : new_fwder->CreateSession();
2325 0 : new_fwder->Connect();
2326 0 : new_fwder->SetSocketOptions();
2327 0 : std::replace(tcpForwarder_.begin(),tcpForwarder_.end(), old_fwder, new_fwder);
2328 0 : old_fwder->ClearSessions();
2329 0 : TcpServerManager::DeleteServer(old_fwder);
2330 0 : } else {
2331 0 : LOG(DEBUG,"connection to remote syslog server " << (*it)->GetIpAddress() << ":"<< (*it)->GetPort() << " is fine");
2332 : }
2333 : }
2334 0 : return true;
2335 : }
2336 :
2337 0 : void StructuredSyslogForwarder::Shutdown() {
2338 0 : if (kafkaForwarder_ != NULL) {
2339 0 : kafkaForwarder_->Shutdown();
2340 : }
2341 0 : LOG(DEBUG, __func__ << " structured_syslog_forwarder shutdown done");
2342 0 : }
2343 :
2344 0 : bool StructuredSyslogForwarder::kafkaForwarder() {
2345 0 : return (kafkaForwarder_ != NULL);
2346 : }
2347 :
2348 0 : void StructuredSyslogForwarder::Forward(boost::shared_ptr<StructuredSyslogQueueEntry> sqe) {
2349 0 : for (std::vector<StructuredSyslogTcpForwarder*>::iterator it = tcpForwarder_.begin();
2350 0 : it != tcpForwarder_.end(); ++it) {
2351 : size_t bytes_written;
2352 0 : (*it)->Send((const u_int8_t*)sqe->data->c_str(), sqe->length, &bytes_written);
2353 0 : if (bytes_written < sqe->length) {
2354 0 : LOG(DEBUG, "error writing - bytes_written: " << bytes_written);
2355 : }
2356 : }
2357 0 : if (kafkaForwarder_ != NULL) {
2358 0 : LOG(DEBUG, "forwarding json - " << *(sqe->json_data));
2359 0 : kafkaForwarder_->Send(*(sqe->json_data), *(sqe->skey));
2360 : }
2361 0 : }
2362 :
2363 0 : StructuredSyslogQueueEntry::StructuredSyslogQueueEntry(boost::shared_ptr<std::string> d, size_t len,
2364 : boost::shared_ptr<std::string> jd,
2365 0 : boost::shared_ptr<std::string> key):
2366 0 : length(len), data(d), json_data(jd),skey(key) {
2367 0 : }
2368 :
2369 0 : StructuredSyslogQueueEntry::~StructuredSyslogQueueEntry() {
2370 0 : }
2371 :
2372 : } // namespace structured_syslog
|