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