Add RFC5424 syslog protocol support (VPP-1139)

Syslog protocol logging transport event messages across network over UDP
protocol based on RFC5426.

Change-Id: Ica74b40bcc2e6d0fbd41e9bf78e76395fbabab3c
Signed-off-by: Matus Fabian <matfabia@cisco.com>
This commit is contained in:
Matus Fabian
2018-11-19 04:25:32 -08:00
committed by Ole Trøan
parent 19ca78fbd7
commit b4515b4be4
14 changed files with 1690 additions and 1 deletions

View File

@ -11,3 +11,4 @@ Programming notes for developers.
- @subpage acl_multicore
- @subpage acl_lookup_context
- @subpage libmemif_doc
- @subpage syslog_doc

View File

@ -1354,6 +1354,23 @@ list(APPEND VNET_HEADERS
list(APPEND VNET_API_FILES bier/bier.api)
##############################################################################
# SYSLOG
##############################################################################
list (APPEND VNET_SOURCES
syslog/syslog_api.c
syslog/syslog_udp.c
syslog/syslog.c
)
list(APPEND VNET_HEADERS
syslog/syslog_udp.h
syslog/syslog.h
)
list(APPEND VNET_API_FILES syslog/syslog.api)
##############################################################################
# VNET Library
##############################################################################

18
src/vnet/syslog/dir.dox Normal file
View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2018 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
@dir
@brief RFC5424 syslog protocol implementation
*/

View File

@ -0,0 +1,65 @@
# Syslog protocol support {#syslog_doc}
VPP provides [RFC5424](https://tools.ietf.org/html/rfc5424) syslog protocol
logging, which is used to transport event messages across network. VPP
currently suports UDP transport based on
[RFC5426](https://tools.ietf.org/html/rfc5426).
The syslog message has the following format:
* header
* structured data
* free-form message
The header contains, priority, version, timestamp, hostname, application,
process id and message id. It is followed by structured data, which provides
a mechanism to express event data in easily parsable format. Structured data
can contain zero, one or multiple structured data elements. Structured data
element contains name-value pairs. Structured data can by followed by free-form
message.
Following example explains how to use the internal APIs to genrate syslog
message:
```{.c}
#include <vnet/syslog/syslog.h>
...
syslog_msg_t syslog_msg;
/* Check if syslog logging is enabled */
if (!syslog_is_enabled ())
return;
/* Severity filer test */
if (syslog_severity_filter_block (severity))
return;
/* Initialize syslog message header */
syslog_msg_init (&syslog_msg, facility, severity, "NAT", "SADD");
/* Create structured data element */
syslog_msg_sd_init (&syslog_msg, "nsess");
/* Add structured data element parameters (name-value pairs) */
syslog_msg_add_sd_param (&syslog_msg, "SSUBIX", "%d", ssubix);
syslog_msg_add_sd_param (&syslog_msg, "SVLAN", "%d", svlan);
syslog_msg_add_sd_param (&syslog_msg, "IATYP", "IPv4");
syslog_msg_add_sd_param (&syslog_msg, "ISADDR", "%U",
format_ip4_address, isaddr);
syslog_msg_add_sd_param (&syslog_msg, "ISPORT", "%d", isport);
syslog_msg_add_sd_param (&syslog_msg, "XATYP", "IPv4");
syslog_msg_add_sd_param (&syslog_msg, "XSADDR", "%U",
format_ip4_address, xsaddr);
syslog_msg_add_sd_param (&syslog_msg, "XSPORT", "%d", xsport);
syslog_msg_add_sd_param (&syslog_msg, "PROTO", "%d", proto);
/* Send syslog message */
syslog_msg_send (&syslog_msg);
```
Example above produces following syslog message:
<134>1 2018-11-12T11:25:30.252715Z 172.16.4.1 NAT 5901 SADD [nsess SSUBIX="0" SVLAN="0" IATYP="IPv4" ISADDR="172.16.1.2" ISPORT="6303" XATYP="IPv4" XSADDR="10.0.0.3" XSPORT="16253" PROTO="6"]
To add free-form message use:
```{.c}
syslog_msg_add_msg (&syslog_msg, "event log entry");
```

119
src/vnet/syslog/syslog.api Normal file
View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2018 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
option version = "1.0.0";
import "vnet/ip/ip_types.api";
enum syslog_severity
{
SYSLOG_API_SEVERITY_EMERG = 0,
SYSLOG_API_SEVERITY_ALERT = 1,
SYSLOG_API_SEVERITY_CRIT = 2,
SYSLOG_API_SEVERITY_ERR = 3,
SYSLOG_API_SEVERITY_WARN = 4,
SYSLOG_API_SEVERITY_NOTICE = 5,
SYSLOG_API_SEVERITY_INFO = 6,
SYSLOG_API_SEVERITY_DBG = 7,
};
/** \brief Set syslog sender configuration
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param src_address - IPv4 address of syslog sender (source)
@param collector_address - IPv4 address of syslog collector (destination)
@param collector_port - UDP port of syslog colector (destination)
@param vrf_id - VRF/FIB table ID
@param max_msg_size - maximum message length
*/
autoreply define syslog_set_sender
{
u32 client_index;
u32 context;
vl_api_ip4_address_t src_address;
vl_api_ip4_address_t collector_address;
u16 collector_port;
u32 vrf_id;
u32 max_msg_size;
};
/** \brief Get syslog sender configuration
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
*/
define syslog_get_sender
{
u32 client_index;
u32 context;
};
/** \brief Get syslog sender configuration reply
@param context - sender context, to match reply w/ request
@param retval - return code for the request
@param src_address - IPv4 address of syslog sender (source)
@param collector_address - IPv4 address of syslog collector (destination)
@param collector_port - UDP port of syslog colector (destination)
@param vrf_id - VRF/FIB table ID
@param max_msg_size - maximum message length
*/
define syslog_get_sender_reply
{
u32 context;
i32 retval;
vl_api_ip4_address_t src_address;
vl_api_ip4_address_t collector_address;
u16 collector_port;
u32 vrf_id;
u32 max_msg_size;
};
/** \brief Set syslog filter
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param severity - severity filter (specified severity and greater match)
*/
autoreply define syslog_set_filter
{
u32 client_index;
u32 context;
vl_api_syslog_severity_t severity;
};
/** \brief Get syslog filter
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
*/
define syslog_get_filter
{
u32 client_index;
u32 context;
};
/** \brief Get syslog filter reply
@param context - sender context, to match reply w/ request
@param retval - return code for the request
@param severity - severity filter (specified severity and greater match)
*/
define syslog_get_filter_reply
{
u32 context;
i32 retval;
vl_api_syslog_severity_t severity;
};
/*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

646
src/vnet/syslog/syslog.c Normal file

File diff suppressed because it is too large Load Diff

225
src/vnet/syslog/syslog.h Normal file
View File

@ -0,0 +1,225 @@
/*
* Copyright (c) 2018 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file RFC5424 syslog protocol declarations
*/
#ifndef __included_syslog_h__
#define __included_syslog_h__
#include <vlib/vlib.h>
#include <vnet/vnet.h>
#include <vnet/ip/ip4_packet.h>
/* syslog message facilities */
#define foreach_syslog_facility \
_(0, KERNEL, "kernel") \
_(1, USER_LEVEL, "user-level") \
_(2, MAIL_SYSTEM, "mail-system") \
_(3, SYSTEM_DAEMONS, "system-daemons") \
_(4, SEC_AUTH, "security-authorization") \
_(5, SYSLOGD, "syslogd") \
_(6, LINE_PRINTER, "line-printer") \
_(7, NETWORK_NEWS, "network-news") \
_(8, UUCP, "uucp") \
_(9, CLOCK, "clock-daemon") \
_(11, FTP, "ftp-daemon") \
_(12, NTP, "ntp-subsystem") \
_(13, LOG_AUDIT, "log-audit") \
_(14, LOG_ALERT, "log-alert") \
_(16, LOCAL0, "local0") \
_(17, LOCAL1, "local1") \
_(18, LOCAL2, "local2") \
_(19, LOCAL3, "local3") \
_(20, LOCAL4, "local4") \
_(21, LOCAL5, "local5") \
_(22, LOCAL6, "local6") \
_(23, LOCAL7, "local7")
typedef enum
{
#define _(v, N, s) SYSLOG_FACILITY_##N = v,
foreach_syslog_facility
#undef _
} syslog_facility_t;
/* syslog message severities */
#define foreach_syslog_severity \
_(0, EMERGENCY, "emergency") \
_(1, ALERT, "alert") \
_(2, CRITICAL, "critical") \
_(3, ERROR, "error") \
_(4, WARNING, "warning") \
_(5, NOTICE, "notice") \
_(6, INFORMATIONAL, "informational") \
_(7, DEBUG, "debug")
typedef enum
{
#define _(v, N, s) SYSLOG_SEVERITY_##N = v,
foreach_syslog_severity
#undef _
} syslog_severity_t;
/** syslog header */
typedef struct
{
/** facility value, part of priority */
syslog_facility_t facility;
/** severity value, part of priority */
syslog_severity_t severity;
/** message timestamp */
f64 timestamp;
/** application that originated the message RFC5424 6.2.5. */
char *app_name;
/** identify the type of message RFC5424 6.2.7. */
char *msgid;
} syslog_header_t;
/** syslog message */
typedef struct
{
/** header */
syslog_header_t header;
/** structured data RFC5424 6.3. */
u8 **structured_data;
u32 curr_sd_index;
/** free-form message RFC5424 6.4. */
u8 *msg;
} syslog_msg_t;
typedef struct
{
/** process ID RFC5424 6.2.6. */
u32 procid;
/** time offset */
f64 time_offset;
/** IPv4 address of remote host (destination) */
ip4_address_t collector;
/** UDP port number of remote host (destination) */
u16 collector_port;
/** IPv4 address of sender (source) */
ip4_address_t src_address;
/** FIB table index */
u32 fib_index;
/** message size limit */
u32 max_msg_size;
/** severity filter (specified severity and greater match) */
syslog_severity_t severity_filter;
/** ip4-lookup node index */
u32 ip4_lookup_node_index;
/** convenience variables */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
} syslog_main_t;
extern syslog_main_t syslog_main;
/**
* @brief Initialize syslog message header
*
* @param facility facility value
* @param severity severity level
* @param app_name application that originated message RFC424 6.2.5. (optional)
* @param msgid identify the type of message RFC5424 6.2.7. (optional)
*/
void syslog_msg_init (syslog_msg_t * syslog_msg, syslog_facility_t facility,
syslog_severity_t severity, char *app_name,
char *msgid);
/**
* @brief Initialize structured data element
*
* @param sd_id structured data element name RFC5424 6.3.2.
*/
void syslog_msg_sd_init (syslog_msg_t * syslog_msg, char *sd_id);
/**
* @brief Add structured data elemnt parameter name-value pair RFC5424 6.3.3.
*/
void syslog_msg_add_sd_param (syslog_msg_t * syslog_msg, char *name,
char *fmt, ...);
/**
* @brief Add free-form message RFC5424 6.4.
*/
void syslog_msg_add_msg (syslog_msg_t * syslog_msg, char *fmt, ...);
/**
* @brief Send syslog message
*/
int syslog_msg_send (syslog_msg_t * syslog_msg);
/**
* @brief Set syslog sender configuration
*
* @param collector IPv4 address of syslog collector (destination)
* @param collector_port UDP port of syslog colector (destination)
* @param src IPv4 address of syslog sender (source)
* @param vrf_id VRF/FIB table ID
* @param max_msg_size maximum message length
*/
vnet_api_error_t set_syslog_sender (ip4_address_t * collector,
u16 collector_port, ip4_address_t * src,
u32 vrf_id, u32 max_msg_size);
/**
* @brief Check if syslog logging is enabled
*
* @return 1 if syslog logging is enabled, 0 otherwise
*/
always_inline int
syslog_is_enabled (void)
{
syslog_main_t *sm = &syslog_main;
return sm->collector.as_u32 ? 1 : 0;
}
/**
* @brief Severity filter test
*
* @return 1 if message with specified severity is not selected to be logged
*/
always_inline int
syslog_severity_filter_block (syslog_severity_t s)
{
syslog_main_t *sm = &syslog_main;
return (sm->severity_filter < s);
}
#endif /* __included_syslog_h__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -0,0 +1,243 @@
/*
* Copyright (c) 2018 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <vnet/vnet.h>
#include <vlibmemory/api.h>
#include <vnet/interface.h>
#include <vnet/api_errno.h>
#include <vnet/fib/fib_table.h>
#include <vnet/syslog/syslog.h>
#include <vnet/vnet_msg_enum.h>
#define vl_typedefs /* define message structures */
#include <vnet/vnet_all_api_h.h>
#undef vl_typedefs
#define vl_endianfun /* define message structures */
#include <vnet/vnet_all_api_h.h>
#undef vl_endianfun
/* instantiate all the print functions we know about */
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
#define vl_printfun
#include <vnet/vnet_all_api_h.h>
#undef vl_printfun
#include <vlibapi/api_helper_macros.h>
#define foreach_vpe_api_msg \
_(SYSLOG_SET_SENDER, syslog_set_sender) \
_(SYSLOG_GET_SENDER, syslog_get_sender) \
_(SYSLOG_SET_FILTER, syslog_set_filter) \
_(SYSLOG_GET_FILTER, syslog_get_filter)
static int
syslog_severity_decode (vl_api_syslog_severity_t v, syslog_severity_t * s)
{
v = ntohl (v);
int rv = 0;
switch (v)
{
case SYSLOG_API_SEVERITY_EMERG:
*s = SYSLOG_SEVERITY_EMERGENCY;
break;
case SYSLOG_API_SEVERITY_ALERT:
*s = SYSLOG_SEVERITY_ALERT;
break;
case SYSLOG_API_SEVERITY_CRIT:
*s = SYSLOG_SEVERITY_CRITICAL;
break;
case SYSLOG_API_SEVERITY_ERR:
*s = SYSLOG_SEVERITY_ERROR;
break;
case SYSLOG_API_SEVERITY_WARN:
*s = SYSLOG_SEVERITY_WARNING;
break;
case SYSLOG_API_SEVERITY_NOTICE:
*s = SYSLOG_SEVERITY_NOTICE;
break;
case SYSLOG_API_SEVERITY_INFO:
*s = SYSLOG_SEVERITY_INFORMATIONAL;
break;
case SYSLOG_API_SEVERITY_DBG:
*s = SYSLOG_SEVERITY_DEBUG;
break;
default:
rv = VNET_API_ERROR_INVALID_VALUE;
}
return rv;
}
static int
syslog_severity_encode (syslog_severity_t v, vl_api_syslog_severity_t * s)
{
int rv = 0;
switch (v)
{
case SYSLOG_SEVERITY_EMERGENCY:
*s = SYSLOG_API_SEVERITY_EMERG;
break;
case SYSLOG_SEVERITY_ALERT:
*s = SYSLOG_API_SEVERITY_ALERT;
break;
case SYSLOG_SEVERITY_CRITICAL:
*s = SYSLOG_API_SEVERITY_CRIT;
break;
case SYSLOG_SEVERITY_ERROR:
*s = SYSLOG_API_SEVERITY_ERR;
break;
case SYSLOG_SEVERITY_WARNING:
*s = SYSLOG_API_SEVERITY_WARN;
break;
case SYSLOG_SEVERITY_NOTICE:
*s = SYSLOG_API_SEVERITY_NOTICE;
break;
case SYSLOG_SEVERITY_INFORMATIONAL:
*s = SYSLOG_API_SEVERITY_INFO;
break;
case SYSLOG_SEVERITY_DEBUG:
*s = SYSLOG_API_SEVERITY_DBG;
break;
default:
rv = VNET_API_ERROR_INVALID_VALUE;
}
*s = htonl (*s);
return rv;
}
static void
vl_api_syslog_set_sender_t_handler (vl_api_syslog_set_sender_t * mp)
{
vl_api_syslog_set_sender_reply_t *rmp;
ip4_address_t collector, src;
clib_memcpy (&collector, &mp->collector_address, sizeof (collector));
clib_memcpy (&src, &mp->src_address, sizeof (src));
int rv = set_syslog_sender (&collector, ntohs (mp->collector_port), &src,
ntohl (mp->vrf_id), ntohl (mp->max_msg_size));
REPLY_MACRO (VL_API_SYSLOG_SET_SENDER_REPLY);
}
static void
vl_api_syslog_get_sender_t_handler (vl_api_syslog_get_sender_t * mp)
{
int rv = 0;
vl_api_syslog_get_sender_reply_t *rmp;
syslog_main_t *sm = &syslog_main;
u32 vrf_id;
/* *INDENT-OFF* */
REPLY_MACRO2 (VL_API_SYSLOG_GET_SENDER_REPLY,
({
clib_memcpy (rmp->collector_address.address, &(sm->collector),
sizeof(ip4_address_t));
clib_memcpy (rmp->src_address.address, &(sm->src_address),
sizeof(ip4_address_t));
rmp->collector_port = htons (sm->collector_port);
if (sm->fib_index == ~0)
vrf_id = ~0;
else
vrf_id = htonl (fib_table_get_table_id (sm->fib_index, FIB_PROTOCOL_IP4));
rmp->vrf_id = vrf_id;
rmp->max_msg_size = htonl (sm->max_msg_size);
}))
/* *INDENT-ON* */
}
static void
vl_api_syslog_set_filter_t_handler (vl_api_syslog_set_filter_t * mp)
{
vl_api_syslog_set_filter_reply_t *rmp;
syslog_main_t *sm = &syslog_main;
int rv = 0;
syslog_severity_t s;
rv = syslog_severity_decode (mp->severity, &s);
if (rv)
goto send_reply;
sm->severity_filter = s;
send_reply:
REPLY_MACRO (VL_API_SYSLOG_SET_FILTER_REPLY);
}
static void
vl_api_syslog_get_filter_t_handler (vl_api_syslog_get_filter_t * mp)
{
int rv = 0;
vl_api_syslog_get_filter_reply_t *rmp;
syslog_main_t *sm = &syslog_main;
/* *INDENT-OFF* */
REPLY_MACRO2 (VL_API_SYSLOG_GET_FILTER_REPLY,
({
rv = syslog_severity_encode (sm->severity_filter, &rmp->severity);
}))
/* *INDENT-ON* */
}
#define vl_msg_name_crc_list
#include <vnet/vnet_all_api_h.h>
#undef vl_msg_name_crc_list
static void
setup_message_id_table (api_main_t * am)
{
#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
foreach_vl_msg_name_crc_syslog;
#undef _
}
static clib_error_t *
syslog_api_hookup (vlib_main_t * vm)
{
api_main_t *am = &api_main;
#define _(N,n) \
vl_msg_api_set_handlers(VL_API_##N, #n, \
vl_api_##n##_t_handler, \
vl_noop_handler, \
vl_api_##n##_t_endian, \
vl_api_##n##_t_print, \
sizeof(vl_api_##n##_t), 1);
foreach_vpe_api_msg;
#undef _
/*
* Set up the (msg_name, crc, message-id) table
*/
setup_message_id_table (am);
return 0;
}
VLIB_API_INIT_FUNCTION (syslog_api_hookup);
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2018 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file syslog protocol UDP transport layer implementation (RFC5426)
*/
#include <vnet/syslog/syslog_udp.h>
#include <vnet/ip/ip4.h>
#include <vnet/udp/udp_packet.h>
void
syslog_add_udp_transport (vlib_main_t * vm, u32 bi)
{
syslog_main_t *sm = &syslog_main;
vlib_buffer_t *b = vlib_get_buffer (vm, bi);
ip4_header_t *ip;
udp_header_t *udp;
vlib_buffer_advance (b, -(sizeof (ip4_header_t) + sizeof (udp_header_t)));
b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
vnet_buffer (b)->sw_if_index[VLIB_TX] = sm->fib_index;
ip = vlib_buffer_get_current (b);
clib_memset (ip, 0, sizeof (*ip));
udp = (udp_header_t *) (ip + 1);
clib_memset (udp, 0, sizeof (*udp));
ip->ip_version_and_header_length = 0x45;
ip->flags_and_fragment_offset =
clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT);
ip->ttl = 255;
ip->protocol = IP_PROTOCOL_UDP;
ip->src_address.as_u32 = sm->src_address.as_u32;
ip->dst_address.as_u32 = sm->collector.as_u32;
udp->src_port = udp->dst_port = clib_host_to_net_u16 (sm->collector_port);
const u16 ip_length = vlib_buffer_length_in_chain (vm, b);
ip->length = clib_host_to_net_u16 (ip_length);
ip->checksum = ip4_header_checksum (ip);
const u16 udp_length = ip_length - (sizeof (ip4_header_t));
udp->length = clib_host_to_net_u16 (udp_length);
/* RFC5426 3.6. */
udp->checksum = ip4_tcp_udp_compute_checksum (vm, b, ip);
if (udp->checksum == 0)
udp->checksum = 0xffff;
b->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2018 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file syslog protocol UDP transport layer declaration (RFC5426)
*/
#ifndef __included_syslog_udp_h__
#define __included_syslog_udp_h__
#include <vnet/syslog/syslog.h>
/**
* @brief Add UDP/IP transport layer by prepending it to existing data
*/
void syslog_add_udp_transport (vlib_main_t * vm, u32 bi);
#endif /* __included_syslog_udp_h__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -76,6 +76,7 @@
#include <vnet/dhcp/dhcp6_ia_na_client_cp.api.h>
#include <vnet/devices/pipe/pipe.api.h>
#include <vnet/vxlan-gbp/vxlan_gbp.api.h>
#include <vnet/syslog/syslog.api.h>
/*
* fd.io coding-style-patch-verification: ON

View File

@ -73,7 +73,7 @@ PYTHON_EXTRA_DEPENDS=
endif
PYTHON_VENV_PATH=$(VPP_PYTHON_PREFIX)/virtualenv
PYTHON_DEPENDS=$(PYTHON_EXTRA_DEPENDS) psutil faulthandler six scapy==2.4.0 pexpect cryptography subprocess32 cffi git+https://github.com/vpp-dev/py-lispnetworking
PYTHON_DEPENDS=$(PYTHON_EXTRA_DEPENDS) psutil faulthandler six scapy==2.4.0 pexpect cryptography subprocess32 cffi syslog-rfc5424-parser git+https://github.com/vpp-dev/py-lispnetworking
SCAPY_SOURCE=$(shell find $(PYTHON_VENV_PATH) -name site-packages)
BUILD_COV_DIR=$(BR)/test-cov

196
test/test_syslog.py Normal file
View File

@ -0,0 +1,196 @@
#!/usr/bin/env python
from framework import VppTestCase, VppTestRunner
from util import ppp
from scapy.packet import Raw
from scapy.layers.inet import IP, UDP
from vpp_papi_provider import SYSLOG_SEVERITY
from syslog_rfc5424_parser import SyslogMessage, ParseError
from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
class TestSyslog(VppTestCase):
""" Syslog Protocol Test Cases """
@classmethod
def setUpClass(cls):
super(TestSyslog, cls).setUpClass()
try:
cls.create_pg_interfaces(range(1))
cls.pg0.admin_up()
cls.pg0.config_ip4()
cls.pg0.resolve_arp()
except Exception:
super(TestSyslog, cls).tearDownClass()
raise
def syslog_generate(self, facility, severity, appname, msgid, sd=None,
msg=None):
"""
Generate syslog message
:param facility: facility value
:param severity: severity level
:param appname: application name that originate message
:param msgid: message indetifier
:param sd: structured data (optional)
:param msg: free-form message (optional)
"""
facility_str = ['kernel', 'user-level', 'mail-system',
'system-daemons', 'security-authorization', 'syslogd',
'line-printer', 'network-news', 'uucp', 'clock-daemon',
'', 'ftp-daemon', 'ntp-subsystem', 'log-audit',
'log-alert', '', 'local0', 'local1', 'local2',
'local3', 'local4', 'local5', 'local6', 'local7']
severity_str = ['emergency', 'alert', 'critical', 'error', 'warning',
'notice', 'informational', 'debug']
cli_str = "test syslog %s %s %s %s" % (facility_str[facility],
severity_str[severity],
appname,
msgid)
if sd is not None:
for sd_id, sd_params in sd.items():
cli_str += " sd-id %s" % (sd_id)
for name, value in sd_params.items():
cli_str += " sd-param %s %s" % (name, value)
if msg is not None:
cli_str += " %s" % (msg)
self.vapi.cli(cli_str)
def syslog_verify(self, data, facility, severity, appname, msgid, sd=None,
msg=None):
"""
Verify syslog message
:param data: syslog message
:param facility: facility value
:param severity: severity level
:param appname: application name that originate message
:param msgid: message indetifier
:param sd: structured data (optional)
:param msg: free-form message (optional)
"""
message = data.decode('utf-8')
if sd is None:
sd = {}
try:
message = SyslogMessage.parse(message)
self.assertEqual(message.facility, facility)
self.assertEqual(message.severity, severity)
self.assertEqual(message.appname, appname)
self.assertEqual(message.msgid, msgid)
self.assertEqual(message.msg, msg)
self.assertEqual(message.sd, sd)
self.assertEqual(message.version, 1)
self.assertEqual(message.hostname, self.pg0.local_ip4)
except ParseError as e:
self.logger.error(e)
def test_syslog(self):
""" Syslog Protocol test """
self.vapi.syslog_set_sender(self.pg0.remote_ip4n, self.pg0.local_ip4n)
config = self.vapi.syslog_get_sender()
self.assertEqual(config.collector_address.address,
self.pg0.remote_ip4n)
self.assertEqual(config.collector_port, 514)
self.assertEqual(config.src_address.address, self.pg0.local_ip4n)
self.assertEqual(config.vrf_id, 0)
self.assertEqual(config.max_msg_size, 480)
appname = 'test'
msgid = 'testMsg'
msg = 'this is message'
sd1 = {'exampleSDID@32473': {'iut': '3',
'eventSource': 'App',
'eventID': '1011'}}
sd2 = {'exampleSDID@32473': {'iut': '3',
'eventSource': 'App',
'eventID': '1011'},
'examplePriority@32473': {'class': 'high'}}
self.pg_enable_capture(self.pg_interfaces)
self.syslog_generate(SyslogFacility.local7,
SyslogSeverity.info,
appname,
msgid,
None,
msg)
capture = self.pg0.get_capture(1)
try:
self.assertEqual(capture[0][IP].src, self.pg0.local_ip4)
self.assertEqual(capture[0][IP].dst, self.pg0.remote_ip4)
self.assertEqual(capture[0][UDP].dport, 514)
self.assert_packet_checksums_valid(capture[0], False)
except:
self.logger.error(ppp("invalid packet:", capture[0]))
raise
self.syslog_verify(capture[0][Raw].load,
SyslogFacility.local7,
SyslogSeverity.info,
appname,
msgid,
None,
msg)
self.pg_enable_capture(self.pg_interfaces)
self.vapi.syslog_set_filter(SYSLOG_SEVERITY.WARN)
filter = self.vapi.syslog_get_filter()
self.assertEqual(filter.severity, SYSLOG_SEVERITY.WARN)
self.syslog_generate(SyslogFacility.local7,
SyslogSeverity.info,
appname,
msgid,
None,
msg)
self.pg0.assert_nothing_captured()
self.pg_enable_capture(self.pg_interfaces)
self.syslog_generate(SyslogFacility.local6,
SyslogSeverity.warning,
appname,
msgid,
sd1,
msg)
capture = self.pg0.get_capture(1)
self.syslog_verify(capture[0][Raw].load,
SyslogFacility.local6,
SyslogSeverity.warning,
appname,
msgid,
sd1,
msg)
self.vapi.syslog_set_sender(self.pg0.remote_ip4n,
self.pg0.local_ip4n,
collector_port=12345)
config = self.vapi.syslog_get_sender()
self.assertEqual(config.collector_port, 12345)
self.pg_enable_capture(self.pg_interfaces)
self.syslog_generate(SyslogFacility.local5,
SyslogSeverity.err,
appname,
msgid,
sd2,
None)
capture = self.pg0.get_capture(1)
try:
self.assertEqual(capture[0][UDP].dport, 12345)
except:
self.logger.error(ppp("invalid packet:", capture[0]))
raise
self.syslog_verify(capture[0][Raw].load,
SyslogFacility.local5,
SyslogSeverity.err,
appname,
msgid,
sd2,
None)
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)

View File

@ -44,6 +44,17 @@ class QOS_SOURCE:
IP = 3
class SYSLOG_SEVERITY:
EMERG = 0
ALERT = 1
CRIT = 2
ERR = 3
WARN = 4
NOTICE = 5
INFO = 6
DBG = 7
class UnexpectedApiReturnValueError(Exception):
""" exception raised when the API return value is unexpected """
pass
@ -4026,3 +4037,42 @@ class VppPapiProvider(object):
def svs_dump(self):
return self.api(self.papi.svs_dump, {})
def syslog_set_sender(
self,
collector,
src,
collector_port=514,
vrf_id=0,
max_msg_size=480):
"""Set syslog sender configuration
:param collector: colector IP address
:param src: source IP address
:param collector_port: collector UDP port (Default value = 514)
:param vrf_id: VRF id (Default value = 0)
:param max_msg_size: maximum message length (Default value = 480)
"""
return self.api(self.papi.syslog_set_sender,
{'collector_address': {
'address': collector},
'src_address': {
'address': src},
'collector_port': collector_port,
'vrf_id': vrf_id,
'max_msg_size': max_msg_size})
def syslog_get_sender(self):
"""Return syslog sender configuration"""
return self.api(self.papi.syslog_get_sender, {})
def syslog_set_filter(self, severity):
"""Set syslog filter parameters
:param severity: severity filter (specified severity and greater match)
"""
return self.api(self.papi.syslog_set_filter, {'severity': severity})
def syslog_get_filter(self):
"""Return syslog filter parameters"""
return self.api(self.papi.syslog_get_filter, {})