mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 01:51:26 +00:00
ovn: Add support for ACL logging.
Signed-off-by: Justin Pettit <jpettit@ovn.org> Acked-by: Han Zhou <zhouhan@gmail.com> Acked-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
parent
19536b6a4b
commit
d383eed595
1
NEWS
1
NEWS
@ -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)).
|
||||
|
@ -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 {
|
||||
@ -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);
|
||||
@ -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. */
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
@ -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));
|
||||
|
105
ovn/lib/acl-log.c
Normal file
105
ovn/lib/acl-log.c
Normal file
@ -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
ovn/lib/acl-log.h
Normal file
54
ovn/lib/acl-log.h
Normal file
@ -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 */
|
@ -33,6 +33,7 @@
|
||||
#include "ovn/actions.h"
|
||||
#include "ovn/expr.h"
|
||||
#include "ovn/lex.h"
|
||||
#include "ovn/lib/acl-log.h"
|
||||
#include "packets.h"
|
||||
#include "openvswitch/shash.h"
|
||||
#include "simap.h"
|
||||
@ -1759,6 +1760,119 @@ ovnact_dns_lookup_free(struct ovnact_dns_lookup *dl OVS_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
parse_log_arg(struct action_context *ctx, struct ovnact_log *log)
|
||||
{
|
||||
if (lexer_match_id(ctx->lexer, "verdict")) {
|
||||
if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
|
||||
return;
|
||||
}
|
||||
if (lexer_match_id(ctx->lexer, "drop")) {
|
||||
log->verdict = LOG_VERDICT_DROP;
|
||||
} else if (lexer_match_id(ctx->lexer, "reject")) {
|
||||
log->verdict = LOG_VERDICT_REJECT;
|
||||
} else if (lexer_match_id(ctx->lexer, "allow")) {
|
||||
log->verdict = LOG_VERDICT_ALLOW;
|
||||
} else {
|
||||
lexer_syntax_error(ctx->lexer, "unknown acl verdict");
|
||||
}
|
||||
} else if (lexer_match_id(ctx->lexer, "name")) {
|
||||
if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
|
||||
return;
|
||||
}
|
||||
/* If multiple names are given, use the most recent. */
|
||||
if (ctx->lexer->token.type == LEX_T_STRING) {
|
||||
/* Arbitrarily limit the name length to 64 bytes, since
|
||||
* these will be encoded in datapath actions. */
|
||||
if (strlen(ctx->lexer->token.s) >= 64) {
|
||||
lexer_syntax_error(ctx->lexer, "name must be shorter "
|
||||
"than 64 characters");
|
||||
return;
|
||||
}
|
||||
free(log->name);
|
||||
log->name = xstrdup(ctx->lexer->token.s);
|
||||
} else {
|
||||
lexer_syntax_error(ctx->lexer, "expecting string");
|
||||
return;
|
||||
}
|
||||
lexer_get(ctx->lexer);
|
||||
} else if (lexer_match_id(ctx->lexer, "severity")) {
|
||||
if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
|
||||
return;
|
||||
}
|
||||
if (ctx->lexer->token.type == LEX_T_ID) {
|
||||
uint8_t severity = log_severity_from_string(ctx->lexer->token.s);
|
||||
if (severity != UINT8_MAX) {
|
||||
log->severity = severity;
|
||||
lexer_get(ctx->lexer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
lexer_syntax_error(ctx->lexer, "expecting severity");
|
||||
} else {
|
||||
lexer_syntax_error(ctx->lexer, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_LOG(struct action_context *ctx)
|
||||
{
|
||||
struct ovnact_log *log = ovnact_put_LOG(ctx->ovnacts);
|
||||
|
||||
/* Provide default values. */
|
||||
log->severity = LOG_SEVERITY_INFO;
|
||||
log->verdict = LOG_VERDICT_UNKNOWN;
|
||||
|
||||
if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
|
||||
while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
|
||||
parse_log_arg(ctx, log);
|
||||
if (ctx->lexer->error) {
|
||||
return;
|
||||
}
|
||||
lexer_match(ctx->lexer, LEX_T_COMMA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
format_LOG(const struct ovnact_log *log, struct ds *s)
|
||||
{
|
||||
ds_put_cstr(s, "log(");
|
||||
|
||||
if (log->name) {
|
||||
ds_put_format(s, "name=\"%s\", ", log->name);
|
||||
}
|
||||
|
||||
ds_put_format(s, "verdict=%s, ", log_verdict_to_string(log->verdict));
|
||||
ds_put_format(s, "severity=%s);", log_severity_to_string(log->severity));
|
||||
}
|
||||
|
||||
static void
|
||||
encode_LOG(const struct ovnact_log *log,
|
||||
const struct ovnact_encode_params *ep OVS_UNUSED,
|
||||
struct ofpbuf *ofpacts)
|
||||
{
|
||||
size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_LOG, false,
|
||||
ofpacts);
|
||||
|
||||
struct log_pin_header *lph = ofpbuf_put_uninit(ofpacts, sizeof *lph);
|
||||
lph->verdict = log->verdict;
|
||||
lph->severity = log->severity;
|
||||
|
||||
if (log->name) {
|
||||
int name_len = strlen(log->name);
|
||||
ofpbuf_put(ofpacts, log->name, name_len);
|
||||
}
|
||||
|
||||
encode_finish_controller_op(oc_offset, ofpacts);
|
||||
}
|
||||
|
||||
static void
|
||||
ovnact_log_free(struct ovnact_log *log)
|
||||
{
|
||||
free(log->name);
|
||||
}
|
||||
|
||||
/* Parses an assignment or exchange or put_dhcp_opts action. */
|
||||
static void
|
||||
parse_set_action(struct action_context *ctx)
|
||||
@ -1838,6 +1952,8 @@ parse_action(struct action_context *ctx)
|
||||
parse_put_mac_bind(ctx, 128, ovnact_put_PUT_ND(ctx->ovnacts));
|
||||
} else if (lexer_match_id(ctx->lexer, "set_queue")) {
|
||||
parse_SET_QUEUE(ctx);
|
||||
} else if (lexer_match_id(ctx->lexer, "log")) {
|
||||
parse_LOG(ctx);
|
||||
} else {
|
||||
lexer_syntax_error(ctx->lexer, "expecting action");
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ ovn_lib_libovn_la_LDFLAGS = \
|
||||
-Wl,--version-script=$(top_builddir)/ovn/lib/libovn.sym \
|
||||
$(AM_LDFLAGS)
|
||||
ovn_lib_libovn_la_SOURCES = \
|
||||
ovn/lib/acl-log.c \
|
||||
ovn/lib/acl-log.h \
|
||||
ovn/lib/actions.c \
|
||||
ovn/lib/chassis-index.c \
|
||||
ovn/lib/chassis-index.h \
|
||||
|
@ -3019,6 +3019,40 @@ build_pre_stateful(struct ovn_datapath *od, struct hmap *lflows)
|
||||
REGBIT_CONNTRACK_DEFRAG" == 1", "ct_next;");
|
||||
}
|
||||
|
||||
static void
|
||||
build_acl_log(struct ds *actions, const struct nbrec_acl *acl)
|
||||
{
|
||||
if (!acl->log) {
|
||||
return;
|
||||
}
|
||||
|
||||
ds_put_cstr(actions, "log(");
|
||||
|
||||
if (acl->name) {
|
||||
ds_put_format(actions, "name=\"%s\", ", acl->name);
|
||||
}
|
||||
|
||||
/* If a severity level isn't specified, default to "info". */
|
||||
if (acl->severity) {
|
||||
ds_put_format(actions, "severity=%s, ", acl->severity);
|
||||
} else {
|
||||
ds_put_format(actions, "severity=info, ");
|
||||
}
|
||||
|
||||
if (!strcmp(acl->action, "drop")) {
|
||||
ds_put_cstr(actions, "verdict=drop, ");
|
||||
} else if (!strcmp(acl->action, "reject")) {
|
||||
ds_put_cstr(actions, "verdict=reject, ");
|
||||
} else if (!strcmp(acl->action, "allow")
|
||||
|| !strcmp(acl->action, "allow-related")) {
|
||||
ds_put_cstr(actions, "verdict=allow, ");
|
||||
}
|
||||
|
||||
ds_chomp(actions, ' ');
|
||||
ds_chomp(actions, ',');
|
||||
ds_put_cstr(actions, "); ");
|
||||
}
|
||||
|
||||
static void
|
||||
build_acls(struct ovn_datapath *od, struct hmap *lflows)
|
||||
{
|
||||
@ -3133,11 +3167,17 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
|
||||
* may and then its return traffic would not have an
|
||||
* associated conntrack entry and would return "+invalid". */
|
||||
if (!has_stateful) {
|
||||
struct ds actions = DS_EMPTY_INITIALIZER;
|
||||
build_acl_log(&actions, acl);
|
||||
ds_put_cstr(&actions, "next;");
|
||||
ovn_lflow_add_with_hint(lflows, od, stage,
|
||||
acl->priority + OVN_ACL_PRI_OFFSET,
|
||||
acl->match, "next;", stage_hint);
|
||||
acl->match, ds_cstr(&actions),
|
||||
stage_hint);
|
||||
ds_destroy(&actions);
|
||||
} else {
|
||||
struct ds match = DS_EMPTY_INITIALIZER;
|
||||
struct ds actions = DS_EMPTY_INITIALIZER;
|
||||
|
||||
/* Commit the connection tracking entry if it's a new
|
||||
* connection that matches this ACL. After this commit,
|
||||
@ -3155,10 +3195,13 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
|
||||
" || (!ct.new && ct.est && !ct.rpl "
|
||||
"&& ct_label.blocked == 1)) "
|
||||
"&& (%s)", acl->match);
|
||||
ds_put_cstr(&actions, REGBIT_CONNTRACK_COMMIT" = 1; ");
|
||||
build_acl_log(&actions, acl);
|
||||
ds_put_cstr(&actions, "next;");
|
||||
ovn_lflow_add_with_hint(lflows, od, stage,
|
||||
acl->priority + OVN_ACL_PRI_OFFSET,
|
||||
ds_cstr(&match),
|
||||
REGBIT_CONNTRACK_COMMIT" = 1; next;",
|
||||
ds_cstr(&actions),
|
||||
stage_hint);
|
||||
|
||||
/* Match on traffic in the request direction for an established
|
||||
@ -3168,20 +3211,26 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
|
||||
* connection is still allowed by the currently defined
|
||||
* policy. */
|
||||
ds_clear(&match);
|
||||
ds_clear(&actions);
|
||||
ds_put_format(&match,
|
||||
"!ct.new && ct.est && !ct.rpl"
|
||||
" && ct_label.blocked == 0 && (%s)",
|
||||
acl->match);
|
||||
|
||||
build_acl_log(&actions, acl);
|
||||
ds_put_cstr(&actions, "next;");
|
||||
ovn_lflow_add_with_hint(lflows, od, stage,
|
||||
acl->priority + OVN_ACL_PRI_OFFSET,
|
||||
ds_cstr(&match), "next;",
|
||||
ds_cstr(&match), ds_cstr(&actions),
|
||||
stage_hint);
|
||||
|
||||
ds_destroy(&match);
|
||||
ds_destroy(&actions);
|
||||
}
|
||||
} else if (!strcmp(acl->action, "drop")
|
||||
|| !strcmp(acl->action, "reject")) {
|
||||
struct ds match = DS_EMPTY_INITIALIZER;
|
||||
struct ds actions = DS_EMPTY_INITIALIZER;
|
||||
|
||||
/* XXX Need to support "reject", treat it as "drop;" for now. */
|
||||
if (!strcmp(acl->action, "reject")) {
|
||||
@ -3199,9 +3248,12 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
|
||||
"(!ct.est || (ct.est && ct_label.blocked == 1)) "
|
||||
"&& (%s)",
|
||||
acl->match);
|
||||
ds_clear(&actions);
|
||||
build_acl_log(&actions, acl);
|
||||
ds_put_cstr(&actions, "/* drop */");
|
||||
ovn_lflow_add_with_hint(lflows, od, stage,
|
||||
acl->priority + OVN_ACL_PRI_OFFSET,
|
||||
ds_cstr(&match), "drop;",
|
||||
ds_cstr(&match), ds_cstr(&actions),
|
||||
stage_hint);
|
||||
|
||||
/* For an existing connection without ct_label set, we've
|
||||
@ -3215,25 +3267,32 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
|
||||
* ct_commit() to the "stateful" stage, but since we're
|
||||
* dropping the packet, we go ahead and do it here. */
|
||||
ds_clear(&match);
|
||||
ds_clear(&actions);
|
||||
ds_put_format(&match,
|
||||
"ct.est && ct_label.blocked == 0 && (%s)",
|
||||
acl->match);
|
||||
ds_put_cstr(&actions, "ct_commit(ct_label=1/1); ");
|
||||
build_acl_log(&actions, acl);
|
||||
ds_put_cstr(&actions, "/* drop */");
|
||||
ovn_lflow_add_with_hint(lflows, od, stage,
|
||||
acl->priority + OVN_ACL_PRI_OFFSET,
|
||||
ds_cstr(&match),
|
||||
"ct_commit(ct_label=1/1);",
|
||||
ds_cstr(&match), ds_cstr(&actions),
|
||||
stage_hint);
|
||||
|
||||
ds_destroy(&match);
|
||||
} else {
|
||||
/* There are no stateful ACLs in use on this datapath,
|
||||
* so a "drop" ACL is simply the "drop" logical flow action
|
||||
* in all cases. */
|
||||
ds_clear(&actions);
|
||||
build_acl_log(&actions, acl);
|
||||
ds_put_cstr(&actions, "/* drop */");
|
||||
ovn_lflow_add_with_hint(lflows, od, stage,
|
||||
acl->priority + OVN_ACL_PRI_OFFSET,
|
||||
acl->match, "drop;", stage_hint);
|
||||
ds_destroy(&match);
|
||||
acl->match, ds_cstr(&actions),
|
||||
stage_hint);
|
||||
}
|
||||
ds_destroy(&match);
|
||||
ds_destroy(&actions);
|
||||
}
|
||||
free(stage_hint);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "OVN_Northbound",
|
||||
"version": "5.7.0",
|
||||
"cksum": "3754583060 16164",
|
||||
"version": "5.8.0",
|
||||
"cksum": "2812300190 16766",
|
||||
"tables": {
|
||||
"NB_Global": {
|
||||
"columns": {
|
||||
@ -116,7 +116,7 @@
|
||||
"isRoot": true},
|
||||
"Load_Balancer": {
|
||||
"columns": {
|
||||
"name": {"type": "string"},
|
||||
"name": {"type": "string"},
|
||||
"vips": {
|
||||
"type": {"key": "string", "value": "string",
|
||||
"min": 0, "max": "unlimited"}},
|
||||
@ -130,6 +130,9 @@
|
||||
"isRoot": true},
|
||||
"ACL": {
|
||||
"columns": {
|
||||
"name": {"type": {"key": {"type": "string",
|
||||
"maxLength": 63},
|
||||
"min": 0, "max": 1}},
|
||||
"priority": {"type": {"key": {"type": "integer",
|
||||
"minInteger": 0,
|
||||
"maxInteger": 32767}}},
|
||||
@ -139,6 +142,12 @@
|
||||
"action": {"type": {"key": {"type": "string",
|
||||
"enum": ["set", ["allow", "allow-related", "drop", "reject"]]}}},
|
||||
"log": {"type": "boolean"},
|
||||
"severity": {"type": {"key": {"type": "string",
|
||||
"enum": ["set",
|
||||
["alert", "warning",
|
||||
"notice", "info",
|
||||
"debug"]]},
|
||||
"min": 0, "max": 1}},
|
||||
"external_ids": {
|
||||
"type": {"key": "string", "value": "string",
|
||||
"min": 0, "max": "unlimited"}}},
|
||||
|
@ -1035,17 +1035,43 @@
|
||||
</ul>
|
||||
</column>
|
||||
|
||||
<column name="log">
|
||||
<group title="Logging">
|
||||
<p>
|
||||
If set to <code>true</code>, packets that match the ACL will trigger a
|
||||
log message on the transport node or nodes that perform ACL processing.
|
||||
Logging may be combined with any <ref column="action"/>.
|
||||
These columns control whether and how OVN logs packets that match an
|
||||
ACL.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Logging is not yet implemented.
|
||||
</p>
|
||||
</column>
|
||||
<column name="log">
|
||||
<p>
|
||||
If set to <code>true</code>, packets that match the ACL will trigger
|
||||
a log message on the transport node or nodes that perform ACL
|
||||
processing. Logging may be combined with any <ref column="action"/>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If set to <code>false</code>, the remaining columns in this group
|
||||
have no significance.
|
||||
</p>
|
||||
</column>
|
||||
|
||||
<column name="name">
|
||||
<p>
|
||||
This name, if it is provided, is included in log records. It
|
||||
provides the administrator and the cloud management system a way to
|
||||
associate a log record with a particular ACL.
|
||||
</p>
|
||||
</column>
|
||||
|
||||
<column name="severity">
|
||||
<p>
|
||||
The severity of the ACL. The severity levels match those of syslog,
|
||||
in decreasing level of severity: <code>alert</code>,
|
||||
<code>warning</code>, <code>notice</code>, <code>info</code>, or
|
||||
<code>debug</code>. When the column is empty, the default is
|
||||
<code>info</code>.
|
||||
</p>
|
||||
</column>
|
||||
</group>
|
||||
|
||||
<group title="Common Columns">
|
||||
<column name="external_ids">
|
||||
|
@ -1515,6 +1515,47 @@
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<code>log(<var>key</var>=<var>value</var>, </code>...<code>);</code>
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
<p>
|
||||
Causes <code>ovn-controller</code> to log the packet on the chassis
|
||||
that processes it. Packet logging currently uses the same logging
|
||||
mechanism as other Open vSwitch and OVN messages, which means that
|
||||
whether and where log messages appear depends on the local logging
|
||||
configuration that can be configured with <code>ovs-appctl</code>,
|
||||
etc.
|
||||
</p>
|
||||
<p>
|
||||
The <code>log</code> action takes zero or more of the following
|
||||
key-value pair arguments that control what is logged:
|
||||
</p>
|
||||
<dl>
|
||||
<dt><code>name=</code><var>string</var></dt>
|
||||
<dd>
|
||||
An optional name for the ACL. The <var>string</var> is
|
||||
currently limited to 64 bytes.
|
||||
</dd>
|
||||
<dt><code>severity=</code><var>level</var></dt>
|
||||
<dd>
|
||||
Indicates the severity of the event. The <var>level</var> is one
|
||||
of following (from more to less serious): <code>alert</code>,
|
||||
<code>warning</code>, <code>notice</code>, <code>info</code>, or
|
||||
<code>debug</code>. If a severity is not provided, the default
|
||||
is <code>info</code>.
|
||||
</dd>
|
||||
<dt><code>verdict=</code><var>value</var></dt>
|
||||
<dd>
|
||||
The verdict for packets matching the flow. The value must be one
|
||||
of <code>allow</code>, <code>deny</code>, or <code>reject</code>.
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
The following actions will likely be useful later, but they have not
|
||||
been thought out carefully.
|
||||
|
@ -76,17 +76,29 @@
|
||||
|
||||
<h1>Logical Switch ACL Commands</h1>
|
||||
<dl>
|
||||
<dt>[<code>--log</code>] [<code>--may-exist</code>] <code>acl-add</code> <var>switch</var> <var>direction</var> <var>priority</var> <var>match</var> <var>action</var></dt>
|
||||
<dt>[<code>--log</code>] [<code>--severity=</code><var>severity</var>] [<code>--name=</code><var>name</var>] [<code>--may-exist</code>] <code>acl-add</code> <var>switch</var> <var>direction</var> <var>priority</var> <var>match</var> <var>verdict</var></dt>
|
||||
<dd>
|
||||
Adds the specified ACL to <var>switch</var>.
|
||||
<var>direction</var> must be either <code>from-lport</code> or
|
||||
<code>to-lport</code>. <var>priority</var> must be between
|
||||
<code>0</code> and <code>32767</code>, inclusive. If
|
||||
<code>--log</code> is specified, packet logging is enabled for the
|
||||
ACL. A full description of the fields are in <code>ovn-nb</code>(5).
|
||||
If <code>--may-exist</code> is specified, adding a duplicated ACL
|
||||
succeeds but the ACL is not really created. Without <code>--may-exist</code>,
|
||||
adding a duplicated ACL results in error.
|
||||
<p>
|
||||
Adds the specified ACL to <var>switch</var>.
|
||||
<var>direction</var> must be either <code>from-lport</code> or
|
||||
<code>to-lport</code>. <var>priority</var> must be between
|
||||
<code>0</code> and <code>32767</code>, inclusive. A full
|
||||
description of the fields are in <code>ovn-nb</code>(5). If
|
||||
<code>--may-exist</code> is specified, adding a duplicated ACL
|
||||
succeeds but the ACL is not really created. Without
|
||||
<code>--may-exist</code>, adding a duplicated ACL results in
|
||||
error.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>--log</code> option enables packet logging for the ACL.
|
||||
The options <code>--severity</code> and <code>--name</code> specify a
|
||||
severity and name, respectively, for log entries (and also enable
|
||||
logging). The severity must be one of <code>alert</code>,
|
||||
<code>warning</code>, <code>notice</code>, <code>info</code>, or
|
||||
<code>debug</code>. If a severity is not specified, the default is
|
||||
<code>info</code>.
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dt><code>acl-del</code> <var>switch</var> [<var>direction</var> [<var>priority</var> <var>match</var>]]</dt>
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "dirs.h"
|
||||
#include "fatal-signal.h"
|
||||
#include "openvswitch/json.h"
|
||||
#include "ovn/lib/acl-log.h"
|
||||
#include "ovn/lib/ovn-nb-idl.h"
|
||||
#include "ovn/lib/ovn-util.h"
|
||||
#include "packets.h"
|
||||
@ -332,7 +333,8 @@ Logical switch commands:\n\
|
||||
ls-list print the names of all logical switches\n\
|
||||
\n\
|
||||
ACL commands:\n\
|
||||
acl-add SWITCH DIRECTION PRIORITY MATCH ACTION [log]\n\
|
||||
[--log] [--severity=SEVERITY] [--name=NAME] [--may-exist]\n\
|
||||
acl-add SWITCH DIRECTION PRIORITY MATCH ACTION\n\
|
||||
add an ACL to SWITCH\n\
|
||||
acl-del SWITCH [DIRECTION [PRIORITY MATCH]]\n\
|
||||
remove ACLs from SWITCH\n\
|
||||
@ -1311,9 +1313,21 @@ nbctl_acl_list(struct ctl_context *ctx)
|
||||
|
||||
for (i = 0; i < ls->n_acls; i++) {
|
||||
const struct nbrec_acl *acl = acls[i];
|
||||
ds_put_format(&ctx->output, "%10s %5"PRId64" (%s) %s%s\n",
|
||||
acl->direction, acl->priority,
|
||||
acl->match, acl->action, acl->log ? " log" : "");
|
||||
ds_put_format(&ctx->output, "%10s %5"PRId64" (%s) %s",
|
||||
acl->direction, acl->priority, acl->match,
|
||||
acl->action);
|
||||
if (acl->log) {
|
||||
ds_put_cstr(&ctx->output, " log(");
|
||||
if (acl->name) {
|
||||
ds_put_format(&ctx->output, "name=%s,", acl->name);
|
||||
}
|
||||
if (acl->severity) {
|
||||
ds_put_format(&ctx->output, "severity=%s", acl->severity);
|
||||
}
|
||||
ds_chomp(&ctx->output, ',');
|
||||
ds_put_cstr(&ctx->output, ")");
|
||||
}
|
||||
ds_put_cstr(&ctx->output, "\n");
|
||||
}
|
||||
|
||||
free(acls);
|
||||
@ -1369,9 +1383,23 @@ nbctl_acl_add(struct ctl_context *ctx)
|
||||
nbrec_acl_set_direction(acl, direction);
|
||||
nbrec_acl_set_match(acl, ctx->argv[4]);
|
||||
nbrec_acl_set_action(acl, action);
|
||||
if (shash_find(&ctx->options, "--log") != NULL) {
|
||||
|
||||
/* Logging options. */
|
||||
bool log = shash_find(&ctx->options, "--log") != NULL;
|
||||
const char *severity = shash_find_data(&ctx->options, "--severity");
|
||||
const char *name = shash_find_data(&ctx->options, "--name");
|
||||
if (log || severity || name) {
|
||||
nbrec_acl_set_log(acl, true);
|
||||
}
|
||||
if (severity) {
|
||||
if (log_severity_from_string(severity) == UINT8_MAX) {
|
||||
ctl_fatal("bad severity: %s", severity);
|
||||
}
|
||||
nbrec_acl_set_severity(acl, severity);
|
||||
}
|
||||
if (name) {
|
||||
nbrec_acl_set_name(acl, name);
|
||||
}
|
||||
|
||||
/* Check if same acl already exists for the ls */
|
||||
for (size_t i = 0; i < ls->n_acls; i++) {
|
||||
@ -3292,6 +3320,8 @@ static const struct ctl_table_class tables[NBREC_N_TABLES] = {
|
||||
|
||||
[NBREC_TABLE_ADDRESS_SET].row_ids[0]
|
||||
= {&nbrec_address_set_col_name, NULL, NULL},
|
||||
|
||||
[NBREC_TABLE_ACL].row_ids[0] = {&nbrec_acl_col_name, NULL, NULL},
|
||||
};
|
||||
|
||||
static void
|
||||
@ -3543,8 +3573,8 @@ static const struct ctl_command_syntax nbctl_commands[] = {
|
||||
{ "ls-list", 0, 0, "", NULL, nbctl_ls_list, NULL, "", RO },
|
||||
|
||||
/* acl commands. */
|
||||
{ "acl-add", 5, 5, "SWITCH DIRECTION PRIORITY MATCH ACTION", NULL,
|
||||
nbctl_acl_add, NULL, "--log,--may-exist", RW },
|
||||
{ "acl-add", 5, 6, "SWITCH DIRECTION PRIORITY MATCH ACTION", NULL,
|
||||
nbctl_acl_add, NULL, "--log,--may-exist,--name=,--severity=", RW },
|
||||
{ "acl-del", 1, 4, "SWITCH [DIRECTION [PRIORITY MATCH]]", NULL,
|
||||
nbctl_acl_del, NULL, "", RW },
|
||||
{ "acl-list", 1, 1, "SWITCH", NULL, nbctl_acl_list, NULL, "", RO },
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "ovn/actions.h"
|
||||
#include "ovn/expr.h"
|
||||
#include "ovn/lex.h"
|
||||
#include "ovn/lib/acl-log.h"
|
||||
#include "ovn/lib/logical-fields.h"
|
||||
#include "ovn/lib/ovn-sb-idl.h"
|
||||
#include "ovn/lib/ovn-dhcp.h"
|
||||
@ -1681,6 +1682,20 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat,
|
||||
* flow, not ct_flow. */
|
||||
}
|
||||
|
||||
static void
|
||||
execute_log(const struct ovnact_log *log, struct flow *uflow,
|
||||
struct ovs_list *super)
|
||||
{
|
||||
char *packet_str = flow_to_string(uflow, NULL);
|
||||
ovntrace_node_append(super, OVNTRACE_NODE_TRANSFORMATION,
|
||||
"LOG: ACL name=%s, verdict=%s, severity=%s, packet=\"%s\"",
|
||||
log->name ? log->name : "<unnamed>",
|
||||
log_verdict_to_string(log->verdict),
|
||||
log_severity_to_string(log->severity),
|
||||
packet_str);
|
||||
free(packet_str);
|
||||
}
|
||||
|
||||
static void
|
||||
trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
|
||||
const struct ovntrace_datapath *dp, struct flow *uflow,
|
||||
@ -1816,6 +1831,10 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
|
||||
case OVNACT_DNS_LOOKUP:
|
||||
execute_dns_lookup(ovnact_get_DNS_LOOKUP(a), uflow, super);
|
||||
break;
|
||||
|
||||
case OVNACT_LOG:
|
||||
execute_log(ovnact_get_LOG(a), uflow, super);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ OVN_NBCTL_TEST_START
|
||||
|
||||
AT_CHECK([ovn-nbctl ls-add ls0])
|
||||
AT_CHECK([ovn-nbctl --log acl-add ls0 from-lport 600 udp drop])
|
||||
AT_CHECK([ovn-nbctl --log acl-add ls0 to-lport 500 udp drop])
|
||||
AT_CHECK([ovn-nbctl --log --name=test --severity=info acl-add ls0 to-lport 500 udp drop])
|
||||
AT_CHECK([ovn-nbctl acl-add ls0 from-lport 400 tcp drop])
|
||||
AT_CHECK([ovn-nbctl acl-add ls0 to-lport 300 tcp drop])
|
||||
AT_CHECK([ovn-nbctl acl-add ls0 from-lport 200 ip drop])
|
||||
@ -206,10 +206,10 @@ AT_CHECK([grep 'already existed' stderr], [0], [ignore])
|
||||
AT_CHECK([ovn-nbctl --may-exist acl-add ls0 to-lport 100 ip drop])
|
||||
|
||||
AT_CHECK([ovn-nbctl acl-list ls0], [0], [dnl
|
||||
from-lport 600 (udp) drop log
|
||||
from-lport 600 (udp) drop log()
|
||||
from-lport 400 (tcp) drop
|
||||
from-lport 200 (ip) drop
|
||||
to-lport 500 (udp) drop log
|
||||
to-lport 500 (udp) drop log(name=test,severity=info)
|
||||
to-lport 300 (tcp) drop
|
||||
to-lport 100 (ip) drop
|
||||
])
|
||||
@ -217,7 +217,7 @@ from-lport 200 (ip) drop
|
||||
dnl Delete in one direction.
|
||||
AT_CHECK([ovn-nbctl acl-del ls0 to-lport])
|
||||
AT_CHECK([ovn-nbctl acl-list ls0], [0], [dnl
|
||||
from-lport 600 (udp) drop log
|
||||
from-lport 600 (udp) drop log()
|
||||
from-lport 400 (tcp) drop
|
||||
from-lport 200 (ip) drop
|
||||
])
|
||||
|
105
tests/ovn.at
105
tests/ovn.at
@ -5741,6 +5741,111 @@ OVN_CLEANUP([hv1],[hv2])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([ovn -- ACL logging])
|
||||
AT_KEYWORDS([ovn])
|
||||
ovn_start
|
||||
|
||||
net_add n1
|
||||
|
||||
sim_add hv
|
||||
as hv
|
||||
ovs-vsctl add-br br-phys
|
||||
ovn_attach n1 br-phys 192.168.0.1
|
||||
for i in lp1 lp2; do
|
||||
ovs-vsctl -- add-port br-int $i -- \
|
||||
set interface $i external-ids:iface-id=$i \
|
||||
options:tx_pcap=hv/$i-tx.pcap \
|
||||
options:rxq_pcap=hv/$i-rx.pcap
|
||||
done
|
||||
|
||||
lp1_mac="f0:00:00:00:00:01"
|
||||
lp1_ip="192.168.1.2"
|
||||
|
||||
lp2_mac="f0:00:00:00:00:02"
|
||||
lp2_ip="192.168.1.3"
|
||||
|
||||
ovn-nbctl ls-add lsw0
|
||||
ovn-nbctl --wait=sb lsp-add lsw0 lp1
|
||||
ovn-nbctl --wait=sb lsp-add lsw0 lp2
|
||||
ovn-nbctl lsp-set-addresses lp1 $lp1_mac
|
||||
ovn-nbctl lsp-set-addresses lp2 $lp2_mac
|
||||
ovn-nbctl --wait=sb sync
|
||||
|
||||
ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==80' drop
|
||||
ovn-nbctl --log --severity=alert --name=drop-flow acl-add lsw0 to-lport 1000 'tcp.dst==81' drop
|
||||
|
||||
ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==82' allow
|
||||
ovn-nbctl --log --severity=info --name=allow-flow acl-add lsw0 to-lport 1000 'tcp.dst==83' allow
|
||||
|
||||
ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==84' allow-related
|
||||
ovn-nbctl --log acl-add lsw0 to-lport 1000 'tcp.dst==85' allow-related
|
||||
|
||||
ovn-nbctl acl-add lsw0 to-lport 1000 'tcp.dst==86' reject
|
||||
ovn-nbctl --log --severity=alert --name=reject-flow acl-add lsw0 to-lport 1000 'tcp.dst==87' reject
|
||||
|
||||
ovn-sbctl dump-flows
|
||||
|
||||
|
||||
# Send packet that should be dropped without logging.
|
||||
packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
|
||||
ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
|
||||
tcp && tcp.flags==2 && tcp.src==4360 && tcp.dst==80"
|
||||
as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
|
||||
|
||||
# Send packet that should be dropped with logging.
|
||||
packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
|
||||
ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
|
||||
tcp && tcp.flags==2 && tcp.src==4361 && tcp.dst==81"
|
||||
as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
|
||||
|
||||
# Send packet that should be allowed without logging.
|
||||
packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
|
||||
ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
|
||||
tcp && tcp.flags==2 && tcp.src==4362 && tcp.dst==82"
|
||||
as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
|
||||
|
||||
# Send packet that should be allowed with logging.
|
||||
packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
|
||||
ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
|
||||
tcp && tcp.flags==2 && tcp.src==4363 && tcp.dst==83"
|
||||
as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
|
||||
|
||||
# Send packet that should allow related flows without logging.
|
||||
packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
|
||||
ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
|
||||
tcp && tcp.flags==2 && tcp.src==4364 && tcp.dst==84"
|
||||
as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
|
||||
|
||||
# Send packet that should allow related flows with logging.
|
||||
packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
|
||||
ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
|
||||
tcp && tcp.flags==2 && tcp.src==4365 && tcp.dst==85"
|
||||
as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
|
||||
|
||||
# Send packet that should allow related flows with logging.
|
||||
packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
|
||||
ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
|
||||
tcp && tcp.flags==2 && tcp.src==4366 && tcp.dst==86"
|
||||
as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
|
||||
|
||||
# Send packet that should allow related flows with logging.
|
||||
packet="inport==\"lp1\" && eth.src==$lp1_mac && eth.dst==$lp2_mac &&
|
||||
ip4 && ip.ttl==64 && ip4.src==$lp1_ip && ip4.dst==$lp2_ip &&
|
||||
tcp && tcp.flags==2 && tcp.src==4367 && tcp.dst==87"
|
||||
as hv ovs-appctl -t ovn-controller inject-pkt "$packet"
|
||||
|
||||
AT_CHECK([grep 'acl_log' hv/ovn-controller.log | sed 's/.*name=/name=/'], [0], [dnl
|
||||
name="drop-flow", verdict=drop, severity=alert: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4361,tp_dst=81,tcp_flags=syn
|
||||
name="allow-flow", verdict=allow, severity=info: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4363,tp_dst=83,tcp_flags=syn
|
||||
name="<unnamed>", verdict=allow, severity=info: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4365,tp_dst=85,tcp_flags=syn
|
||||
name="reject-flow", verdict=reject, severity=alert: tcp,vlan_tci=0x0000,dl_src=f0:00:00:00:00:01,dl_dst=f0:00:00:00:00:02,nw_src=192.168.1.2,nw_dst=192.168.1.3,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=4367,tp_dst=87,tcp_flags=syn
|
||||
])
|
||||
|
||||
OVN_CLEANUP([hv])
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([ovn -- DSCP marking check])
|
||||
AT_KEYWORDS([ovn])
|
||||
ovn_start
|
||||
|
Loading…
x
Reference in New Issue
Block a user