Skip to content

Commit

Permalink
ovn: Add support for ACL logging.
Browse files Browse the repository at this point in the history
Signed-off-by: Justin Pettit <[email protected]>
Acked-by: Han Zhou <[email protected]>
Acked-by: Ben Pfaff <[email protected]>
  • Loading branch information
justinpettit committed Jul 29, 2017
1 parent 19536b6 commit d383eed
Show file tree
Hide file tree
Showing 17 changed files with 677 additions and 66 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Post-v2.7.0
* Multiple chassis may now be specified for L3 gateways. When more than
one chassis is specified, OVN will manage high availability for that
gateway.
* Add support for ACL logging.
- Tracing with ofproto/trace now traces through recirculation.
- OVSDB:
* New support for role-based access control (see ovsdb-server(1)).
Expand Down
66 changes: 42 additions & 24 deletions include/ovn/actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,31 @@ struct simap;
* "ovnact". The structure must have a fixed length, that is, it may not
* end with a flexible array member.
*/
#define OVNACTS \
OVNACT(OUTPUT, ovnact_null) \
OVNACT(NEXT, ovnact_next) \
OVNACT(LOAD, ovnact_load) \
OVNACT(MOVE, ovnact_move) \
OVNACT(EXCHANGE, ovnact_move) \
OVNACT(DEC_TTL, ovnact_null) \
OVNACT(CT_NEXT, ovnact_ct_next) \
OVNACT(CT_COMMIT, ovnact_ct_commit) \
OVNACT(CT_DNAT, ovnact_ct_nat) \
OVNACT(CT_SNAT, ovnact_ct_nat) \
OVNACT(CT_LB, ovnact_ct_lb) \
OVNACT(CT_CLEAR, ovnact_null) \
OVNACT(CLONE, ovnact_nest) \
OVNACT(ARP, ovnact_nest) \
OVNACT(ND_NA, ovnact_nest) \
OVNACT(GET_ARP, ovnact_get_mac_bind) \
OVNACT(PUT_ARP, ovnact_put_mac_bind) \
OVNACT(GET_ND, ovnact_get_mac_bind) \
OVNACT(PUT_ND, ovnact_put_mac_bind) \
OVNACT(PUT_DHCPV4_OPTS, ovnact_put_dhcp_opts) \
OVNACT(PUT_DHCPV6_OPTS, ovnact_put_dhcp_opts) \
OVNACT(SET_QUEUE, ovnact_set_queue) \
OVNACT(DNS_LOOKUP, ovnact_dns_lookup)
#define OVNACTS \
OVNACT(OUTPUT, ovnact_null) \
OVNACT(NEXT, ovnact_next) \
OVNACT(LOAD, ovnact_load) \
OVNACT(MOVE, ovnact_move) \
OVNACT(EXCHANGE, ovnact_move) \
OVNACT(DEC_TTL, ovnact_null) \
OVNACT(CT_NEXT, ovnact_ct_next) \
OVNACT(CT_COMMIT, ovnact_ct_commit) \
OVNACT(CT_DNAT, ovnact_ct_nat) \
OVNACT(CT_SNAT, ovnact_ct_nat) \
OVNACT(CT_LB, ovnact_ct_lb) \
OVNACT(CT_CLEAR, ovnact_null) \
OVNACT(CLONE, ovnact_nest) \
OVNACT(ARP, ovnact_nest) \
OVNACT(ND_NA, ovnact_nest) \
OVNACT(GET_ARP, ovnact_get_mac_bind) \
OVNACT(PUT_ARP, ovnact_put_mac_bind) \
OVNACT(GET_ND, ovnact_get_mac_bind) \
OVNACT(PUT_ND, ovnact_put_mac_bind) \
OVNACT(PUT_DHCPV4_OPTS, ovnact_put_dhcp_opts) \
OVNACT(PUT_DHCPV6_OPTS, ovnact_put_dhcp_opts) \
OVNACT(SET_QUEUE, ovnact_set_queue) \
OVNACT(DNS_LOOKUP, ovnact_dns_lookup) \
OVNACT(LOG, ovnact_log)

/* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */
enum OVS_PACKED_ENUM ovnact_type {
Expand Down Expand Up @@ -265,6 +266,14 @@ struct ovnact_dns_lookup {
struct expr_field dst; /* 1-bit destination field. */
};

/* OVNACT_LOG. */
struct ovnact_log {
struct ovnact ovnact;
uint8_t verdict; /* One of LOG_VERDICT_*. */
uint8_t severity; /* One of LOG_SEVERITY_*. */
char *name;
};

/* Internal use by the helpers below. */
void ovnact_init(struct ovnact *, enum ovnact_type, size_t len);
void *ovnact_put(struct ofpbuf *, enum ovnact_type, size_t len);
Expand Down Expand Up @@ -400,6 +409,15 @@ enum action_opcode {
*
*/
ACTION_OPCODE_DNS_LOOKUP,

/* "log(arguments)".
*
* Arguments are as follows:
* - An 8-bit verdict.
* - An 8-bit severity.
* - A variable length string containing the name.
*/
ACTION_OPCODE_LOG,
};

/* Header. */
Expand Down
9 changes: 9 additions & 0 deletions ovn/controller/ovn-controller.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@
machine-local and do not run over a physical network.
</p>

<h1>ACL Logging</h1>
<p>
ACL log messages are logged through <code>ovn-controller</code>'s
logging mechanism. ACL log entries have the module
<code>acl_log</code> at log level <code>info</code>. Configuring
logging is described below in the <code>Logging Options</code>
section.
</p>

<h1>Options</h1>

<h2>Daemon Options</h2>
Expand Down
5 changes: 5 additions & 0 deletions ovn/controller/pinctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "ovn-controller.h"
#include "ovn/actions.h"
#include "ovn/lex.h"
#include "ovn/lib/acl-log.h"
#include "ovn/lib/logical-fields.h"
#include "ovn/lib/ovn-dhcp.h"
#include "ovn/lib/ovn-util.h"
Expand Down Expand Up @@ -981,6 +982,10 @@ process_packet_in(const struct ofp_header *msg, struct controller_ctx *ctx)
pinctrl_handle_dns_lookup(&packet, &pin, &userdata, &continuation, ctx);
break;

case ACTION_OPCODE_LOG:
handle_acl_log(&headers, &userdata);
break;

default:
VLOG_WARN_RL(&rl, "unrecognized packet-in opcode %"PRIu32,
ntohl(ah->opcode));
Expand Down
105 changes: 105 additions & 0 deletions ovn/lib/acl-log.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2017 Nicira, Inc.
*
* 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 <config.h>
#include "ovn/lib/acl-log.h"
#include <string.h>
#include "flow.h"
#include "openvswitch/json.h"
#include "openvswitch/ofpbuf.h"
#include "openvswitch/vlog.h"


VLOG_DEFINE_THIS_MODULE(acl_log);

const char *
log_verdict_to_string(uint8_t verdict)
{
if (verdict == LOG_VERDICT_ALLOW) {
return "allow";
} else if (verdict == LOG_VERDICT_DROP) {
return "drop";
} else if (verdict == LOG_VERDICT_REJECT) {
return "reject";
} else {
return "<unknown>";
}
}

const char *
log_severity_to_string(uint8_t severity)
{
if (severity == LOG_SEVERITY_ALERT) {
return "alert";
} else if (severity == LOG_SEVERITY_WARNING) {
return "warning";
} else if (severity == LOG_SEVERITY_NOTICE) {
return "notice";
} else if (severity == LOG_SEVERITY_INFO) {
return "info";
} else if (severity == LOG_SEVERITY_DEBUG) {
return "debug";
} else {
return "<unknown>";
}
}

uint8_t
log_severity_from_string(const char *name)
{
if (!strcmp(name, "alert")) {
return LOG_SEVERITY_ALERT;
} else if (!strcmp(name, "warning")) {
return LOG_SEVERITY_WARNING;
} else if (!strcmp(name, "notice")) {
return LOG_SEVERITY_NOTICE;
} else if (!strcmp(name, "info")) {
return LOG_SEVERITY_INFO;
} else if (!strcmp(name, "debug")) {
return LOG_SEVERITY_DEBUG;
} else {
return UINT8_MAX;
}
}

void
handle_acl_log(const struct flow *headers, struct ofpbuf *userdata)
{
if (!VLOG_IS_INFO_ENABLED()) {
return;
}

struct log_pin_header *lph = ofpbuf_try_pull(userdata, sizeof *lph);
if (!lph) {
VLOG_WARN("log data missing");
return;
}

size_t name_len = userdata->size;
char *name = name_len ? xmemdup0(userdata->data, name_len) : NULL;

struct ds ds = DS_EMPTY_INITIALIZER;
ds_put_cstr(&ds, "name=");
json_string_escape(name_len ? name : "<unnamed>", &ds);
ds_put_format(&ds, ", verdict=%s, severity=%s: ",
log_verdict_to_string(lph->verdict),
log_severity_to_string(lph->severity));
flow_format(&ds, headers, NULL);

VLOG_INFO("%s", ds_cstr(&ds));
ds_destroy(&ds);
free(name);
}
54 changes: 54 additions & 0 deletions ovn/lib/acl-log.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2017 Nicira, Inc.
*
* 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.
*/

#ifndef ACL_LOG_H
#define ACL_LOG_H 1

#include <stdint.h>
#include "openvswitch/types.h"

struct ofpbuf;
struct flow;

struct log_pin_header {
uint8_t verdict; /* One of LOG_VERDICT_*. */
uint8_t severity; /* One of LOG_SEVERITY*. */
/* Followed by an optional string containing the rule's name. */
};

enum log_verdict {
LOG_VERDICT_ALLOW,
LOG_VERDICT_DROP,
LOG_VERDICT_REJECT,
LOG_VERDICT_UNKNOWN = UINT8_MAX
};

const char *log_verdict_to_string(uint8_t verdict);


/* Severity levels. Based on RFC5424 levels. */
#define LOG_SEVERITY_ALERT 1
#define LOG_SEVERITY_WARNING 4
#define LOG_SEVERITY_NOTICE 5
#define LOG_SEVERITY_INFO 6
#define LOG_SEVERITY_DEBUG 7

const char *log_severity_to_string(uint8_t severity);
uint8_t log_severity_from_string(const char *name);

void handle_acl_log(const struct flow *headers, struct ofpbuf *userdata);

#endif /* ovn/lib/acl-log.h */
Loading

0 comments on commit d383eed

Please sign in to comment.