[ovs-dev] [PATCH v5 ovn 3/4] ovn-northd: Add CoPP policies for flows that punt packets to ovn-controller.
Lorenzo Bianconi
lorenzo.bianconi at redhat.com
Wed Jun 23 11:05:26 UTC 2021
From: Dumitru Ceara <dceara at redhat.com>
Change the ovn-northd implementation to set the new 'controller_meter'
field for flows that need to punt packets to ovn-controller.
Protocol packets for which CoPP is enforced when sending packets to
ovn-controller (if configured):
- ARP
- ND_NS
- ND_NA
- ND_RA
- DNS
- IGMP
- packets that require ARP resolution before forwarding
- packets that require ND_NS before forwarding
- packets that need to be replied to with ICMP Errors
- packets that need to be replied to with TCP RST
- packets that need to be replied to with DHCP_OPTS
- packets that trigger a SCTP abort action
- contoller_events
- BFD
Co-authored-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
Signed-off-by: Dumitru Ceara <dceara at redhat.com>
---
include/ovn/actions.h | 1 -
lib/actions.c | 50 +---
lib/copp.c | 1 +
lib/copp.h | 1 +
northd/ovn-northd.c | 497 ++++++++++++++++++++++++--------------
ovn-nb.xml | 3 +
tests/atlocal.in | 3 +
tests/ovn.at | 9 +-
tests/system-ovn.at | 138 +++++++++++
utilities/ovn-nbctl.8.xml | 3 +
10 files changed, 477 insertions(+), 229 deletions(-)
diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index a33d02681..f023a37b9 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -394,7 +394,6 @@ struct ovnact_controller_event {
int event_type; /* controller event type */
struct ovnact_gen_option *options;
size_t n_options;
- char *meter;
};
/* OVNACT_BIND_VPORT. */
diff --git a/lib/actions.c b/lib/actions.c
index 2355a9ace..c572e88ae 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -1644,9 +1644,6 @@ format_TRIGGER_EVENT(const struct ovnact_controller_event *event,
{
ds_put_format(s, "trigger_event(event = \"%s\"",
event_to_string(event->event_type));
- if (event->meter) {
- ds_put_format(s, ", meter = \"%s\"", event->meter);
- }
for (const struct ovnact_gen_option *o = event->options;
o < &event->options[event->n_options]; o++) {
ds_put_cstr(s, ", ");
@@ -1821,24 +1818,11 @@ encode_event_empty_lb_backends_opts(struct ofpbuf *ofpacts,
static void
encode_TRIGGER_EVENT(const struct ovnact_controller_event *event,
- const struct ovnact_encode_params *ep OVS_UNUSED,
+ const struct ovnact_encode_params *ep,
struct ofpbuf *ofpacts)
{
- uint32_t meter_id = NX_CTLR_NO_METER;
- size_t oc_offset;
-
- if (event->meter) {
- meter_id = ovn_extend_table_assign_id(ep->meter_table, event->meter,
- ep->lflow_uuid);
- if (meter_id == EXT_TABLE_ID_INVALID) {
- VLOG_WARN("Unable to assign id for trigger meter: %s",
- event->meter);
- return;
- }
- }
-
- oc_offset = encode_start_controller_op(ACTION_OPCODE_EVENT, false,
- meter_id, ofpacts);
+ size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_EVENT, false,
+ ep->ctrl_meter_id, ofpacts);
ovs_be32 ofs = htonl(event->event_type);
ofpbuf_put(ofpacts, &ofs, sizeof ofs);
@@ -2372,27 +2356,12 @@ parse_trigger_event(struct action_context *ctx,
sizeof *event->options);
}
- if (lexer_match_id(ctx->lexer, "meter")) {
- if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
- return;
- }
- /* If multiple meters are given, use the most recent. */
- if (ctx->lexer->token.type == LEX_T_STRING &&
- strlen(ctx->lexer->token.s)) {
- free(event->meter);
- event->meter = xstrdup(ctx->lexer->token.s);
- } else if (ctx->lexer->token.type != LEX_T_STRING) {
- lexer_syntax_error(ctx->lexer, "expecting string");
- return;
- }
- lexer_get(ctx->lexer);
- } else {
- struct ovnact_gen_option *o = &event->options[event->n_options++];
- memset(o, 0, sizeof *o);
- parse_gen_opt(ctx, o,
- &ctx->pp->controller_event_opts->event_opts[event_type],
- event_to_string(event_type));
- }
+ struct ovnact_gen_option *o = &event->options[event->n_options++];
+ memset(o, 0, sizeof *o);
+ parse_gen_opt(ctx, o,
+ &ctx->pp->controller_event_opts->event_opts[event_type],
+ event_to_string(event_type));
+
if (ctx->lexer->error) {
return;
}
@@ -2413,7 +2382,6 @@ static void
ovnact_controller_event_free(struct ovnact_controller_event *event)
{
free_gen_options(event->options, event->n_options);
- free(event->meter);
}
static void
diff --git a/lib/copp.c b/lib/copp.c
index e3d14938a..bbe66924b 100644
--- a/lib/copp.c
+++ b/lib/copp.c
@@ -37,6 +37,7 @@ static char *copp_proto_names[COPP_PROTO_MAX] = {
[COPP_ND_NS_RESOLVE] = "nd-ns-resolve",
[COPP_ND_RA_OPTS] = "nd-ra-opts",
[COPP_TCP_RESET] = "tcp-reset",
+ [COPP_REJECT] = "reject",
[COPP_BFD] = "bfd",
};
diff --git a/lib/copp.h b/lib/copp.h
index c34e1e029..e238d963a 100644
--- a/lib/copp.h
+++ b/lib/copp.h
@@ -36,6 +36,7 @@ enum copp_proto {
COPP_ND_RA_OPTS,
COPP_TCP_RESET,
COPP_BFD,
+ COPP_REJECT,
COPP_PROTO_MAX,
COPP_PROTO_INVALID = COPP_PROTO_MAX,
};
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 4b8cb9ad5..11e45ce77 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -3326,11 +3326,11 @@ ovn_lb_svc_create(struct northd_context *ctx, struct ovn_northd_lb *lb,
}
}
-static
-void build_lb_vip_actions(struct ovn_lb_vip *lb_vip,
- struct ovn_northd_lb_vip *lb_vip_nb,
- struct ds *action, char *selection_fields,
- bool ls_dp)
+static bool
+build_lb_vip_actions(struct ovn_lb_vip *lb_vip,
+ struct ovn_northd_lb_vip *lb_vip_nb,
+ struct ds *action, char *selection_fields,
+ bool ls_dp)
{
bool skip_hash_fields = false, reject = false;
@@ -3382,6 +3382,7 @@ void build_lb_vip_actions(struct ovn_lb_vip *lb_vip,
ds_chomp(action, ')');
ds_put_format(action, "; hash_fields=\"%s\");", selection_fields);
}
+ return reject;
}
static void
@@ -4186,8 +4187,8 @@ ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od,
ovn_lflow_add_at(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, true, \
NULL, NULL, OVS_SOURCE_LOCATOR)
-#define ovn_lflow_add_ctrl(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, \
- CTRL_METER) \
+#define ovn_lflow_metered(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, \
+ CTRL_METER) \
ovn_lflow_add_with_hint__(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, \
ACTIONS, CTRL_METER, NULL)
@@ -4206,9 +4207,14 @@ ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od,
ovn_lflow_add_at(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, false, \
NULL, STAGE_HINT, OVS_SOURCE_LOCATOR)
-#define ovn_lflow_add_unique(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS) \
+#define ovn_lflow_add_unique__(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, \
+ ACTIONS, CTRL_METER) \
ovn_lflow_add_at(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, false, \
- NULL, NULL, OVS_SOURCE_LOCATOR)
+ CTRL_METER, NULL, OVS_SOURCE_LOCATOR)
+
+#define ovn_lflow_add_unique(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS) \
+ ovn_lflow_add_unique__(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, \
+ NULL)
static struct ovn_lflow *
ovn_lflow_find(const struct hmap *lflows, const struct ovn_datapath *od,
@@ -5157,11 +5163,7 @@ build_empty_lb_event_flow(struct ovn_datapath *od, struct hmap *lflows,
bool ipv4 = IN6_IS_ADDR_V4MAPPED(&lb_vip->vip);
struct ds match = DS_EMPTY_INITIALIZER;
- char *meter = "", *action;
-
- if (meter_groups && shash_find(meter_groups, "event-elb")) {
- meter = "event-elb";
- }
+ char *action;
ds_put_format(&match, "ip%s.dst == %s && %s",
ipv4 ? "4": "6", lb_vip->vip_str, lb->protocol);
@@ -5175,14 +5177,18 @@ build_empty_lb_event_flow(struct ovn_datapath *od, struct hmap *lflows,
}
action = xasprintf("trigger_event(event = \"%s\", "
- "meter = \"%s\", vip = \"%s\", "
+ "vip = \"%s\", "
"protocol = \"%s\", "
"load_balancer = \"" UUID_FMT "\");",
event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS),
- meter, vip, lb->protocol,
+ vip, lb->protocol,
UUID_ARGS(&lb->header_.uuid));
- ovn_lflow_add_with_hint(lflows, od, pl, 130, ds_cstr(&match), action,
- &lb->header_);
+
+ const struct nbrec_copp *copp = (od->nbr ? od->nbr->copp : od->nbs->copp);
+ ovn_lflow_add_with_hint__(lflows, od, pl, 130, ds_cstr(&match), action,
+ copp_meter_get(COPP_EVENT_ELB, copp,
+ meter_groups),
+ &lb->header_);
ds_destroy(&match);
if (lb_vip->vip_port) {
free(vip);
@@ -5550,9 +5556,12 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows,
"reject { "
"/* eth.dst <-> eth.src; ip.dst <-> ip.src; is implicit. */ "
"outport <-> inport; %s };", next_action);
- ovn_lflow_add_with_hint(lflows, od, stage,
- acl->priority + OVN_ACL_PRI_OFFSET,
- ds_cstr(&match), ds_cstr(&actions), stage_hint);
+ ovn_lflow_add_with_hint__(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
+ ds_cstr(&match), ds_cstr(&actions),
+ copp_meter_get(COPP_REJECT, od->nbs->copp,
+ meter_groups),
+ stage_hint);
free(next_action);
ds_destroy(&match);
@@ -6052,7 +6061,7 @@ build_qos(struct ovn_datapath *od, struct hmap *lflows) {
static void
build_lb_rules(struct ovn_datapath *od, struct hmap *lflows,
- struct ovn_northd_lb *lb)
+ struct ovn_northd_lb *lb, struct shash *meter_groups)
{
struct ds action = DS_EMPTY_INITIALIZER;
struct ds match = DS_EMPTY_INITIALIZER;
@@ -6097,20 +6106,24 @@ build_lb_rules(struct ovn_datapath *od, struct hmap *lflows,
}
/* New connections in Ingress table. */
- build_lb_vip_actions(lb_vip, lb_vip_nb, &action,
- lb->selection_fields, true);
+ const char *meter = NULL;
+ bool reject = build_lb_vip_actions(lb_vip, lb_vip_nb, &action,
+ lb->selection_fields, true);
+ if (reject) {
+ meter = copp_meter_get(COPP_REJECT, od->nbs->copp, meter_groups);
+ }
ds_put_format(&match, "ct.new && %s.dst == %s", ip_match,
lb_vip->vip_str);
if (lb_vip->vip_port) {
ds_put_format(&match, " && %s.dst == %d", proto, lb_vip->vip_port);
- ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_STATEFUL, 120,
- ds_cstr(&match), ds_cstr(&action),
- &lb->nlb->header_);
+ ovn_lflow_add_with_hint__(lflows, od, S_SWITCH_IN_STATEFUL, 120,
+ ds_cstr(&match), ds_cstr(&action),
+ meter, &lb->nlb->header_);
} else {
- ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_STATEFUL, 110,
- ds_cstr(&match), ds_cstr(&action),
- &lb->nlb->header_);
+ ovn_lflow_add_with_hint__(lflows, od, S_SWITCH_IN_STATEFUL, 110,
+ ds_cstr(&match), ds_cstr(&action),
+ meter, &lb->nlb->header_);
}
}
ds_destroy(&action);
@@ -6118,7 +6131,8 @@ build_lb_rules(struct ovn_datapath *od, struct hmap *lflows,
}
static void
-build_stateful(struct ovn_datapath *od, struct hmap *lflows, struct hmap *lbs)
+build_stateful(struct ovn_datapath *od, struct hmap *lflows,
+ struct hmap *lbs, struct shash *meter_groups)
{
/* Ingress and Egress stateful Table (Priority 0): Packets are
* allowed by default. */
@@ -6146,7 +6160,7 @@ build_stateful(struct ovn_datapath *od, struct hmap *lflows, struct hmap *lbs)
ovn_northd_lb_find(lbs, &od->nbs->load_balancer[i]->header_.uuid);
ovs_assert(lb);
- build_lb_rules(od, lflows, lb);
+ build_lb_rules(od, lflows, lb, meter_groups);
}
}
@@ -6671,6 +6685,7 @@ static void
build_dhcpv4_options_flows(struct ovn_port *op,
struct lport_addresses *lsp_addrs,
const char *json_key, bool is_external,
+ struct shash *meter_groups,
struct hmap *lflows)
{
struct ds match = DS_EMPTY_INITIALIZER;
@@ -6694,11 +6709,14 @@ build_dhcpv4_options_flows(struct ovn_port *op,
op->json_key);
}
- ovn_lflow_add_with_hint(lflows, op->od,
- S_SWITCH_IN_DHCP_OPTIONS, 100,
- ds_cstr(&match),
- ds_cstr(&options_action),
- &op->nbsp->dhcpv4_options->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od,
+ S_SWITCH_IN_DHCP_OPTIONS, 100,
+ ds_cstr(&match),
+ ds_cstr(&options_action),
+ copp_meter_get(COPP_DHCPV4_OPTS,
+ op->od->nbs->copp,
+ meter_groups),
+ &op->nbsp->dhcpv4_options->header_);
ds_clear(&match);
/* Allow ip4.src = OFFER_IP and
* ip4.dst = {SERVER_IP, 255.255.255.255} for the below
@@ -6718,11 +6736,14 @@ build_dhcpv4_options_flows(struct ovn_port *op,
op->json_key);
}
- ovn_lflow_add_with_hint(lflows, op->od,
- S_SWITCH_IN_DHCP_OPTIONS, 100,
- ds_cstr(&match),
- ds_cstr(&options_action),
- &op->nbsp->dhcpv4_options->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od,
+ S_SWITCH_IN_DHCP_OPTIONS, 100,
+ ds_cstr(&match),
+ ds_cstr(&options_action),
+ copp_meter_get(COPP_DHCPV4_OPTS,
+ op->od->nbs->copp,
+ meter_groups),
+ &op->nbsp->dhcpv4_options->header_);
ds_clear(&match);
/* If REGBIT_DHCP_OPTS_RESULT is set, it means the
@@ -6756,6 +6777,7 @@ static void
build_dhcpv6_options_flows(struct ovn_port *op,
struct lport_addresses *lsp_addrs,
const char *json_key, bool is_external,
+ struct shash *meter_groups,
struct hmap *lflows)
{
struct ds match = DS_EMPTY_INITIALIZER;
@@ -6778,11 +6800,14 @@ build_dhcpv6_options_flows(struct ovn_port *op,
op->json_key);
}
- ovn_lflow_add_with_hint(lflows, op->od,
- S_SWITCH_IN_DHCP_OPTIONS, 100,
- ds_cstr(&match),
- ds_cstr(&options_action),
- &op->nbsp->dhcpv6_options->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od,
+ S_SWITCH_IN_DHCP_OPTIONS, 100,
+ ds_cstr(&match),
+ ds_cstr(&options_action),
+ copp_meter_get(COPP_DHCPV6_OPTS,
+ op->od->nbs->copp,
+ meter_groups),
+ &op->nbsp->dhcpv6_options->header_);
/* If REGBIT_DHCP_OPTS_RESULT is set to 1, it means the
* put_dhcpv6_opts action is successful */
@@ -6920,7 +6945,7 @@ build_lswitch_lflows_pre_acl_and_acl(struct ovn_datapath *od,
build_acl_hints(od, lflows);
build_acls(od, lflows, port_groups, meter_groups);
build_qos(od, lflows);
- build_stateful(od, lflows, lbs);
+ build_stateful(od, lflows, lbs, meter_groups);
build_lb_hairpin(od, lflows);
}
}
@@ -6976,6 +7001,7 @@ static void
build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op,
struct hmap *lflows,
struct hmap *ports,
+ struct shash *meter_groups,
struct ds *actions,
struct ds *match)
{
@@ -7117,11 +7143,14 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op,
op->lsp_addrs[i].ipv6_addrs[j].addr_s,
op->lsp_addrs[i].ipv6_addrs[j].addr_s,
op->lsp_addrs[i].ea_s);
- ovn_lflow_add_with_hint(lflows, op->od,
- S_SWITCH_IN_ARP_ND_RSP, 50,
- ds_cstr(match),
- ds_cstr(actions),
- &op->nbsp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od,
+ S_SWITCH_IN_ARP_ND_RSP, 50,
+ ds_cstr(match),
+ ds_cstr(actions),
+ copp_meter_get(COPP_ND_NA,
+ op->od->nbs->copp,
+ meter_groups),
+ &op->nbsp->header_);
/* Do not reply to a solicitation from the port that owns
* the address (otherwise DAD detection will fail). */
@@ -7199,7 +7228,8 @@ build_lswitch_arp_nd_service_monitor(struct ovn_northd_lb *lb,
* priority 100 flows. */
static void
build_lswitch_dhcp_options_and_response(struct ovn_port *op,
- struct hmap *lflows)
+ struct hmap *lflows,
+ struct shash *meter_groups)
{
if (op->nbsp) {
if (!lsp_is_enabled(op->nbsp) || lsp_is_router(op->nbsp)) {
@@ -7228,17 +7258,17 @@ build_lswitch_dhcp_options_and_response(struct ovn_port *op,
build_dhcpv4_options_flows(
op, &op->lsp_addrs[i],
op->od->localnet_ports[j]->json_key, is_external,
- lflows);
+ meter_groups, lflows);
build_dhcpv6_options_flows(
op, &op->lsp_addrs[i],
op->od->localnet_ports[j]->json_key, is_external,
- lflows);
+ meter_groups, lflows);
}
} else {
build_dhcpv4_options_flows(op, &op->lsp_addrs[i], op->json_key,
- is_external, lflows);
+ is_external, meter_groups, lflows);
build_dhcpv6_options_flows(op, &op->lsp_addrs[i], op->json_key,
- is_external, lflows);
+ is_external, meter_groups, lflows);
}
}
}
@@ -7268,13 +7298,15 @@ build_lswitch_dhcp_and_dns_defaults(struct ovn_datapath *od,
*/
static void
build_lswitch_dns_lookup_and_response(struct ovn_datapath *od,
- struct hmap *lflows)
+ struct hmap *lflows,
+ struct shash *meter_groups)
{
if (od->nbs && ls_has_dns_records(od->nbs)) {
-
- ovn_lflow_add(lflows, od, S_SWITCH_IN_DNS_LOOKUP, 100,
- "udp.dst == 53",
- REGBIT_DNS_LOOKUP_RESULT" = dns_lookup(); next;");
+ ovn_lflow_metered(lflows, od, S_SWITCH_IN_DNS_LOOKUP, 100,
+ "udp.dst == 53",
+ REGBIT_DNS_LOOKUP_RESULT" = dns_lookup(); next;",
+ copp_meter_get(COPP_DNS, od->nbs->copp,
+ meter_groups));
const char *dns_action = "eth.dst <-> eth.src; ip4.src <-> ip4.dst; "
"udp.dst = udp.src; udp.src = 53; outport = inport; "
"flags.loopback = 1; output;";
@@ -7311,7 +7343,8 @@ build_lswitch_external_port(struct ovn_port *op,
static void
build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od,
struct hmap *lflows,
- struct ds *actions)
+ struct ds *actions,
+ struct shash *meter_groups)
{
if (od->nbs) {
@@ -7332,12 +7365,16 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od,
}
ds_put_cstr(actions, "igmp;");
/* Punt IGMP traffic to controller. */
- ovn_lflow_add_unique(lflows, od, S_SWITCH_IN_L2_LKUP, 100,
- "ip4 && ip.proto == 2", ds_cstr(actions));
+ ovn_lflow_add_unique__(lflows, od, S_SWITCH_IN_L2_LKUP, 100,
+ "ip4 && ip.proto == 2", ds_cstr(actions),
+ copp_meter_get(COPP_IGMP, od->nbs->copp,
+ meter_groups));
/* Punt MLD traffic to controller. */
- ovn_lflow_add_unique(lflows, od, S_SWITCH_IN_L2_LKUP, 100,
- "mldv1 || mldv2", ds_cstr(actions));
+ ovn_lflow_add_unique__(lflows, od, S_SWITCH_IN_L2_LKUP, 100,
+ "mldv1 || mldv2", ds_cstr(actions),
+ copp_meter_get(COPP_IGMP, od->nbs->copp,
+ meter_groups));
/* Flood all IP multicast traffic destined to 224.0.0.X to all
* ports - RFC 4541, section 2.1.2, item 2.
@@ -8731,23 +8768,29 @@ add_router_lb_flow(struct hmap *lflows, struct ovn_datapath *od,
struct ds *match, struct ds *actions, int priority,
enum lb_snat_type snat_type, struct ovn_lb_vip *lb_vip,
const char *proto, struct nbrec_load_balancer *lb,
- struct shash *meter_groups, struct sset *nat_entries)
+ struct shash *meter_groups, struct sset *nat_entries,
+ bool reject)
{
build_empty_lb_event_flow(od, lflows, lb_vip, lb, S_ROUTER_IN_DNAT,
meter_groups);
+ const char *meter = NULL;
+ if (reject) {
+ meter = copp_meter_get(COPP_REJECT, od->nbr->copp, meter_groups);
+ }
/* A match and actions for new connections. */
char *new_match = xasprintf("ct.new && %s", ds_cstr(match));
if (snat_type == FORCE_SNAT || snat_type == SKIP_SNAT) {
char *new_actions = xasprintf("flags.%s_snat_for_lb = 1; %s",
snat_type == SKIP_SNAT ? "skip" : "force",
ds_cstr(actions));
- ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority,
- new_match, new_actions, &lb->header_);
+ ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_DNAT, priority,
+ new_match, new_actions, meter, &lb->header_);
free(new_actions);
} else {
- ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority,
- new_match, ds_cstr(actions), &lb->header_);
+ ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_DNAT, priority,
+ new_match, ds_cstr(actions), meter,
+ &lb->header_);
}
/* A match and actions for established connections. */
@@ -8873,8 +8916,8 @@ build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od,
struct ovn_lb_vip *lb_vip = &lb->vips[j];
struct ovn_northd_lb_vip *lb_vip_nb = &lb->vips_nb[j];
ds_clear(actions);
- build_lb_vip_actions(lb_vip, lb_vip_nb, actions,
- lb->selection_fields, false);
+ bool reject = build_lb_vip_actions(lb_vip, lb_vip_nb, actions,
+ lb->selection_fields, false);
if (!sset_contains(&all_ips, lb_vip->vip_str)) {
sset_add(&all_ips, lb_vip->vip_str);
@@ -8939,7 +8982,7 @@ build_lrouter_lb_flows(struct hmap *lflows, struct ovn_datapath *od,
}
add_router_lb_flow(lflows, od, match, actions, prio,
snat_type, lb_vip, proto, nb_lb,
- meter_groups, nat_entries);
+ meter_groups, nat_entries, reject);
}
}
sset_destroy(&all_ips);
@@ -9176,7 +9219,7 @@ build_lrouter_nd_flow(struct ovn_datapath *od, struct ovn_port *op,
const char *sn_ip_address, const char *eth_addr,
struct ds *extra_match, bool drop, uint16_t priority,
const struct ovsdb_idl_row *hint,
- struct hmap *lflows)
+ struct hmap *lflows, struct shash *meter_groups)
{
struct ds match = DS_EMPTY_INITIALIZER;
struct ds actions = DS_EMPTY_INITIALIZER;
@@ -9198,6 +9241,8 @@ build_lrouter_nd_flow(struct ovn_datapath *od, struct ovn_port *op,
if (drop) {
ds_put_format(&actions, "drop;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_IP_INPUT, priority,
+ ds_cstr(&match), ds_cstr(&actions), hint);
} else {
ds_put_format(&actions,
"%s { "
@@ -9214,11 +9259,13 @@ build_lrouter_nd_flow(struct ovn_datapath *od, struct ovn_port *op,
ip_address,
ip_address,
eth_addr);
+ ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_IP_INPUT, priority,
+ ds_cstr(&match), ds_cstr(&actions),
+ copp_meter_get(COPP_ND_NA, od->nbr->copp,
+ meter_groups),
+ hint);
}
- ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_IP_INPUT, priority,
- ds_cstr(&match), ds_cstr(&actions), hint);
-
ds_destroy(&match);
ds_destroy(&actions);
}
@@ -9226,7 +9273,8 @@ build_lrouter_nd_flow(struct ovn_datapath *od, struct ovn_port *op,
static void
build_lrouter_nat_arp_nd_flow(struct ovn_datapath *od,
struct ovn_nat *nat_entry,
- struct hmap *lflows)
+ struct hmap *lflows,
+ struct shash *meter_groups)
{
struct lport_addresses *ext_addrs = &nat_entry->ext_addrs;
const struct nbrec_nat *nat = nat_entry->nb;
@@ -9236,7 +9284,7 @@ build_lrouter_nat_arp_nd_flow(struct ovn_datapath *od,
ext_addrs->ipv6_addrs[0].addr_s,
ext_addrs->ipv6_addrs[0].sn_addr_s,
REG_INPORT_ETH_ADDR, NULL, false, 90,
- &nat->header_, lflows);
+ &nat->header_, lflows, meter_groups);
} else {
build_lrouter_arp_flow(od, NULL,
ext_addrs->ipv4_addrs[0].addr_s,
@@ -9248,7 +9296,8 @@ build_lrouter_nat_arp_nd_flow(struct ovn_datapath *od,
static void
build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op,
struct ovn_nat *nat_entry,
- struct hmap *lflows)
+ struct hmap *lflows,
+ struct shash *meter_groups)
{
struct lport_addresses *ext_addrs = &nat_entry->ext_addrs;
const struct nbrec_nat *nat = nat_entry->nb;
@@ -9291,12 +9340,12 @@ build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op,
ext_addrs->ipv6_addrs[0].addr_s,
ext_addrs->ipv6_addrs[0].sn_addr_s,
mac_s, &match, false, 92,
- &nat->header_, lflows);
+ &nat->header_, lflows, meter_groups);
build_lrouter_nd_flow(op->od, op, "nd_na",
ext_addrs->ipv6_addrs[0].addr_s,
ext_addrs->ipv6_addrs[0].sn_addr_s,
mac_s, NULL, true, 91,
- &nat->header_, lflows);
+ &nat->header_, lflows, meter_groups);
} else {
build_lrouter_arp_flow(op->od, op,
ext_addrs->ipv4_addrs[0].addr_s,
@@ -9469,7 +9518,8 @@ build_lrouter_force_snat_flows_op(struct ovn_port *op,
}
static void
-build_lrouter_bfd_flows(struct hmap *lflows, struct ovn_port *op)
+build_lrouter_bfd_flows(struct hmap *lflows, struct ovn_port *op,
+ struct shash *meter_groups)
{
if (!op->has_bfd) {
return;
@@ -9488,9 +9538,11 @@ build_lrouter_bfd_flows(struct hmap *lflows, struct ovn_port *op)
ds_clear(&match);
ds_put_format(&match, "ip4.dst == %s && udp.dst == 3784",
ds_cstr(&ip_list));
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110,
- ds_cstr(&match), "handle_bfd_msg(); ",
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110,
+ ds_cstr(&match), "handle_bfd_msg(); ",
+ copp_meter_get(COPP_BFD, op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
}
if (op->lrp_networks.n_ipv6_addrs) {
ds_clear(&ip_list);
@@ -9505,9 +9557,11 @@ build_lrouter_bfd_flows(struct hmap *lflows, struct ovn_port *op)
ds_clear(&match);
ds_put_format(&match, "ip6.dst == %s && udp.dst == 3784",
ds_cstr(&ip_list));
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110,
- ds_cstr(&match), "handle_bfd_msg(); ",
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT, 110,
+ ds_cstr(&match), "handle_bfd_msg(); ",
+ copp_meter_get(COPP_BFD, op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
}
ds_destroy(&ip_list);
@@ -9587,7 +9641,8 @@ build_adm_ctrl_flows_for_lrouter_port(
static void
build_neigh_learning_flows_for_lrouter(
struct ovn_datapath *od, struct hmap *lflows,
- struct ds *match, struct ds *actions)
+ struct ds *match, struct ds *actions,
+ struct shash *meter_groups)
{
if (od->nbr) {
@@ -9667,14 +9722,20 @@ build_neigh_learning_flows_for_lrouter(
ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 100,
ds_cstr(match), "next;");
- ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90,
- "arp", "put_arp(inport, arp.spa, arp.sha); next;");
+ ovn_lflow_metered(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90,
+ "arp", "put_arp(inport, arp.spa, arp.sha); next;",
+ copp_meter_get(COPP_ARP, od->nbr->copp,
+ meter_groups));
- ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90,
- "nd_na", "put_nd(inport, nd.target, nd.tll); next;");
+ ovn_lflow_metered(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90,
+ "nd_na", "put_nd(inport, nd.target, nd.tll); next;",
+ copp_meter_get(COPP_ND_NA, od->nbr->copp,
+ meter_groups));
- ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90,
- "nd_ns", "put_nd(inport, ip6.src, nd.sll); next;");
+ ovn_lflow_metered(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90,
+ "nd_ns", "put_nd(inport, ip6.src, nd.sll); next;",
+ copp_meter_get(COPP_ND_NS, od->nbr->copp,
+ meter_groups));
}
}
@@ -9749,7 +9810,8 @@ build_neigh_learning_flows_for_lrouter_port(
static void
build_ND_RA_flows_for_lrouter_port(
struct ovn_port *op, struct hmap *lflows,
- struct ds *match, struct ds *actions)
+ struct ds *match, struct ds *actions,
+ struct shash *meter_groups)
{
if (!op->nbrp || op->nbrp->peer || !op->peer) {
return;
@@ -9842,9 +9904,12 @@ build_ND_RA_flows_for_lrouter_port(
if (add_rs_response_flow) {
ds_put_cstr(actions, "); next;");
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ND_RA_OPTIONS,
- 50, ds_cstr(match), ds_cstr(actions),
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_ND_RA_OPTIONS,
+ 50, ds_cstr(match), ds_cstr(actions),
+ copp_meter_get(COPP_ND_RA_OPTS,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
ds_clear(actions);
ds_clear(match);
ds_put_format(match, "inport == %s && ip6.dst == ff02::2 && "
@@ -10467,7 +10532,8 @@ static void
build_check_pkt_len_flows_for_lrouter(
struct ovn_datapath *od, struct hmap *lflows,
struct hmap *ports,
- struct ds *match, struct ds *actions)
+ struct ds *match, struct ds *actions,
+ struct shash *meter_groups)
{
if (od->nbr) {
@@ -10529,10 +10595,14 @@ build_check_pkt_len_flows_for_lrouter(
rp->lrp_networks.ipv4_addrs[0].addr_s,
gw_mtu,
ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
- ovn_lflow_add_with_hint(lflows, od,
- S_ROUTER_IN_LARGER_PKTS, 50,
- ds_cstr(match), ds_cstr(actions),
- &rp->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, od,
+ S_ROUTER_IN_LARGER_PKTS, 50,
+ ds_cstr(match), ds_cstr(actions),
+ copp_meter_get(
+ COPP_ICMP4_ERR,
+ rp->od->nbr->copp,
+ meter_groups),
+ &rp->nbrp->header_);
}
if (rp->lrp_networks.ipv6_addrs) {
@@ -10558,10 +10628,14 @@ build_check_pkt_len_flows_for_lrouter(
rp->lrp_networks.ipv6_addrs[0].addr_s,
gw_mtu,
ovn_stage_get_table(S_ROUTER_IN_ADMISSION));
- ovn_lflow_add_with_hint(lflows, od,
- S_ROUTER_IN_LARGER_PKTS, 50,
- ds_cstr(match), ds_cstr(actions),
- &rp->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, od,
+ S_ROUTER_IN_LARGER_PKTS, 50,
+ ds_cstr(match), ds_cstr(actions),
+ copp_meter_get(
+ COPP_ICMP6_ERR,
+ rp->od->nbr->copp,
+ meter_groups),
+ &rp->nbrp->header_);
}
}
}
@@ -10616,7 +10690,8 @@ build_gateway_redirect_flows_for_lrouter(
static void
build_arp_request_flows_for_lrouter(
struct ovn_datapath *od, struct hmap *lflows,
- struct ds *match, struct ds *actions)
+ struct ds *match, struct ds *actions,
+ struct shash *meter_groups)
{
if (od->nbr) {
for (int i = 0; i < od->nbr->n_static_routes; i++) {
@@ -10653,26 +10728,33 @@ build_arp_request_flows_for_lrouter(
"};", ETH_ADDR_ARGS(eth_dst), sn_addr_s,
route->nexthop);
- ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ARP_REQUEST, 200,
- ds_cstr(match), ds_cstr(actions),
- &route->header_);
- }
-
- ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 100,
- "eth.dst == 00:00:00:00:00:00 && ip4",
- "arp { "
- "eth.dst = ff:ff:ff:ff:ff:ff; "
- "arp.spa = " REG_SRC_IPV4 "; "
- "arp.tpa = " REG_NEXT_HOP_IPV4 "; "
- "arp.op = 1; " /* ARP request */
- "output; "
- "};");
- ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 100,
- "eth.dst == 00:00:00:00:00:00 && ip6",
- "nd_ns { "
- "nd.target = " REG_NEXT_HOP_IPV6 "; "
- "output; "
- "};");
+ ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_ARP_REQUEST, 200,
+ ds_cstr(match), ds_cstr(actions),
+ copp_meter_get(COPP_ND_NS_RESOLVE,
+ od->nbr->copp,
+ meter_groups),
+ &route->header_);
+ }
+
+ ovn_lflow_metered(lflows, od, S_ROUTER_IN_ARP_REQUEST, 100,
+ "eth.dst == 00:00:00:00:00:00 && ip4",
+ "arp { "
+ "eth.dst = ff:ff:ff:ff:ff:ff; "
+ "arp.spa = " REG_SRC_IPV4 "; "
+ "arp.tpa = " REG_NEXT_HOP_IPV4 "; "
+ "arp.op = 1; " /* ARP request */
+ "output; "
+ "};",
+ copp_meter_get(COPP_ARP_RESOLVE, od->nbr->copp,
+ meter_groups));
+ ovn_lflow_metered(lflows, od, S_ROUTER_IN_ARP_REQUEST, 100,
+ "eth.dst == 00:00:00:00:00:00 && ip6",
+ "nd_ns { "
+ "nd.target = " REG_NEXT_HOP_IPV6 "; "
+ "output; "
+ "};",
+ copp_meter_get(COPP_ND_NS_RESOLVE, od->nbr->copp,
+ meter_groups));
ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 0, "1", "output;");
}
}
@@ -10803,7 +10885,8 @@ build_dhcpv6_reply_flows_for_lrouter_port(
static void
build_ipv6_input_flows_for_lrouter_port(
struct ovn_port *op, struct hmap *lflows,
- struct ds *match, struct ds *actions)
+ struct ds *match, struct ds *actions,
+ struct shash *meter_groups)
{
if (op->nbrp && (!op->derived)) {
/* No ingress packets are accepted on a chassisredirect
@@ -10846,7 +10929,7 @@ build_ipv6_input_flows_for_lrouter_port(
op->lrp_networks.ipv6_addrs[i].addr_s,
op->lrp_networks.ipv6_addrs[i].sn_addr_s,
REG_INPORT_ETH_ADDR, match, false, 90,
- &op->nbrp->header_, lflows);
+ &op->nbrp->header_, lflows, meter_groups);
}
/* UDP/TCP/SCTP port unreachable */
@@ -10861,9 +10944,13 @@ build_ipv6_input_flows_for_lrouter_port(
"eth.dst <-> eth.src; "
"ip6.dst <-> ip6.src; "
"next; };";
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
- 80, ds_cstr(match), action,
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(match), action,
+ copp_meter_get(
+ COPP_TCP_RESET,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
ds_clear(match);
ds_put_format(match,
@@ -10873,9 +10960,13 @@ build_ipv6_input_flows_for_lrouter_port(
"eth.dst <-> eth.src; "
"ip6.dst <-> ip6.src; "
"next; };";
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
- 80, ds_cstr(match), action,
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(match), action,
+ copp_meter_get(
+ COPP_TCP_RESET,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
ds_clear(match);
ds_put_format(match,
@@ -10888,9 +10979,13 @@ build_ipv6_input_flows_for_lrouter_port(
"icmp6.type = 1; "
"icmp6.code = 4; "
"next; };";
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
- 80, ds_cstr(match), action,
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(match), action,
+ copp_meter_get(
+ COPP_ICMP6_ERR,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
ds_clear(match);
ds_put_format(match,
@@ -10903,9 +10998,13 @@ build_ipv6_input_flows_for_lrouter_port(
"icmp6.type = 1; "
"icmp6.code = 3; "
"next; };";
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
- 70, ds_cstr(match), action,
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 70, ds_cstr(match), action,
+ copp_meter_get(
+ COPP_ICMP6_ERR,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
}
}
@@ -10936,9 +11035,12 @@ build_ipv6_input_flows_for_lrouter_port(
"icmp6.code = 0; /* TTL exceeded in transit */ "
"next; };",
op->lrp_networks.ipv6_addrs[i].addr_s);
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 40,
- ds_cstr(match), ds_cstr(actions),
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT, 40,
+ ds_cstr(match), ds_cstr(actions),
+ copp_meter_get(COPP_ICMP6_ERR,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
}
}
@@ -10946,7 +11048,8 @@ build_ipv6_input_flows_for_lrouter_port(
static void
build_lrouter_arp_nd_for_datapath(struct ovn_datapath *od,
- struct hmap *lflows)
+ struct hmap *lflows,
+ struct shash *meter_groups)
{
if (od->nbr) {
@@ -10972,7 +11075,7 @@ build_lrouter_arp_nd_for_datapath(struct ovn_datapath *od,
if (!strcmp(nat_entry->nb->type, "snat")) {
continue;
}
- build_lrouter_nat_arp_nd_flow(od, nat_entry, lflows);
+ build_lrouter_nat_arp_nd_flow(od, nat_entry, lflows, meter_groups);
}
/* Now handle SNAT entries too, one per unique SNAT IP. */
@@ -10987,7 +11090,7 @@ build_lrouter_arp_nd_for_datapath(struct ovn_datapath *od,
struct ovn_nat *nat_entry =
CONTAINER_OF(ovs_list_front(&snat_ip->snat_entries),
struct ovn_nat, ext_addr_list_node);
- build_lrouter_nat_arp_nd_flow(od, nat_entry, lflows);
+ build_lrouter_nat_arp_nd_flow(od, nat_entry, lflows, meter_groups);
}
}
}
@@ -10996,7 +11099,8 @@ build_lrouter_arp_nd_for_datapath(struct ovn_datapath *od,
static void
build_lrouter_ipv4_ip_input(struct ovn_port *op,
struct hmap *lflows,
- struct ds *match, struct ds *actions)
+ struct ds *match, struct ds *actions,
+ struct shash *meter_groups)
{
/* No ingress packets are accepted on a chassisredirect
* port, so no need to program flows for that port. */
@@ -11034,7 +11138,7 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
}
/* BFD msg handling */
- build_lrouter_bfd_flows(lflows, op);
+ build_lrouter_bfd_flows(lflows, op, meter_groups);
/* ICMP time exceeded */
for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
@@ -11054,9 +11158,12 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
"ip.ttl = 255; "
"next; };",
op->lrp_networks.ipv4_addrs[i].addr_s);
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 40,
- ds_cstr(match), ds_cstr(actions),
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT, 40,
+ ds_cstr(match), ds_cstr(actions),
+ copp_meter_get(COPP_ICMP4_ERR,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
}
/* ARP reply. These flows reply to ARP requests for the router's own
@@ -11133,7 +11240,8 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
build_lrouter_nd_flow(op->od, op, "nd_na",
ip_address, NULL, REG_INPORT_ETH_ADDR,
- match, false, 90, NULL, lflows);
+ match, false, 90, NULL,
+ lflows, meter_groups);
}
if (!smap_get(&op->od->nbr->options, "chassis")
@@ -11151,9 +11259,13 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
"icmp4.type = 3; "
"icmp4.code = 3; "
"next; };";
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
- 80, ds_cstr(match), action,
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(match), action,
+ copp_meter_get(
+ COPP_ICMP4_ERR,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
ds_clear(match);
ds_put_format(match,
@@ -11163,9 +11275,13 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
"eth.dst <-> eth.src; "
"ip4.dst <-> ip4.src; "
"next; };";
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
- 80, ds_cstr(match), action,
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(match), action,
+ copp_meter_get(
+ COPP_TCP_RESET,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
ds_clear(match);
ds_put_format(match,
@@ -11175,9 +11291,13 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
"eth.dst <-> eth.src; "
"ip4.dst <-> ip4.src; "
"next; };";
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
- 80, ds_cstr(match), action,
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(match), action,
+ copp_meter_get(
+ COPP_TCP_RESET,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
ds_clear(match);
ds_put_format(match,
@@ -11190,9 +11310,13 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
"icmp4.type = 3; "
"icmp4.code = 2; "
"next; };";
- ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
- 70, ds_cstr(match), action,
- &op->nbrp->header_);
+ ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 70, ds_cstr(match), action,
+ copp_meter_get(
+ COPP_ICMP4_ERR,
+ op->od->nbr->copp,
+ meter_groups),
+ &op->nbrp->header_);
}
}
@@ -11236,7 +11360,8 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
if (!strcmp(nat_entry->nb->type, "snat")) {
continue;
}
- build_lrouter_port_nat_arp_nd_flow(op, nat_entry, lflows);
+ build_lrouter_port_nat_arp_nd_flow(op, nat_entry, lflows,
+ meter_groups);
}
/* Now handle SNAT entries too, one per unique SNAT IP. */
@@ -11251,7 +11376,8 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
struct ovn_nat *nat_entry =
CONTAINER_OF(ovs_list_front(&snat_ip->snat_entries),
struct ovn_nat, ext_addr_list_node);
- build_lrouter_port_nat_arp_nd_flow(op, nat_entry, lflows);
+ build_lrouter_port_nat_arp_nd_flow(op, nat_entry, lflows,
+ meter_groups);
}
}
}
@@ -11932,15 +12058,16 @@ build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od,
build_lswitch_input_port_sec_od(od, lsi->lflows);
build_lswitch_learn_fdb_od(od, lsi->lflows);
build_lswitch_arp_nd_responder_default(od, lsi->lflows);
- build_lswitch_dns_lookup_and_response(od, lsi->lflows);
+ build_lswitch_dns_lookup_and_response(od, lsi->lflows, lsi->meter_groups);
build_lswitch_dhcp_and_dns_defaults(od, lsi->lflows);
- build_lswitch_destination_lookup_bmcast(od, lsi->lflows, &lsi->actions);
+ build_lswitch_destination_lookup_bmcast(od, lsi->lflows, &lsi->actions,
+ lsi->meter_groups);
build_lswitch_output_port_sec_od(od, lsi->lflows);
/* Build Logical Router Flows. */
build_adm_ctrl_flows_for_lrouter(od, lsi->lflows);
build_neigh_learning_flows_for_lrouter(od, lsi->lflows, &lsi->match,
- &lsi->actions);
+ &lsi->actions, lsi->meter_groups);
build_ND_RA_flows_for_lrouter(od, lsi->lflows);
build_static_route_flows_for_lrouter(od, lsi->lflows, lsi->ports,
lsi->bfd_connections);
@@ -11949,13 +12076,14 @@ build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od,
build_ingress_policy_flows_for_lrouter(od, lsi->lflows, lsi->ports);
build_arp_resolve_flows_for_lrouter(od, lsi->lflows);
build_check_pkt_len_flows_for_lrouter(od, lsi->lflows, lsi->ports,
- &lsi->match, &lsi->actions);
+ &lsi->match, &lsi->actions,
+ lsi->meter_groups);
build_gateway_redirect_flows_for_lrouter(od, lsi->lflows, &lsi->match,
&lsi->actions);
build_arp_request_flows_for_lrouter(od, lsi->lflows, &lsi->match,
- &lsi->actions);
+ &lsi->actions, lsi->meter_groups);
build_misc_local_traffic_drop_flows_for_lrouter(od, lsi->lflows);
- build_lrouter_arp_nd_for_datapath(od, lsi->lflows);
+ build_lrouter_arp_nd_for_datapath(od, lsi->lflows, lsi->meter_groups);
build_lrouter_nat_defrag_and_lb(od, lsi->lflows, lsi->meter_groups,
lsi->lbs, &lsi->match, &lsi->actions);
}
@@ -11975,9 +12103,11 @@ build_lswitch_and_lrouter_iterate_by_op(struct ovn_port *op,
&lsi->match);
build_lswitch_arp_nd_responder_known_ips(op, lsi->lflows,
lsi->ports,
+ lsi->meter_groups,
&lsi->actions,
&lsi->match);
- build_lswitch_dhcp_options_and_response(op, lsi->lflows);
+ build_lswitch_dhcp_options_and_response(op, lsi->lflows,
+ lsi->meter_groups);
build_lswitch_external_port(op, lsi->lflows);
build_lswitch_ip_unicast_lookup(op, lsi->lflows, lsi->mcgroups,
&lsi->actions, &lsi->match);
@@ -11991,16 +12121,17 @@ build_lswitch_and_lrouter_iterate_by_op(struct ovn_port *op,
&lsi->actions);
build_ip_routing_flows_for_lrouter_port(op, lsi->lflows);
build_ND_RA_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
- &lsi->actions);
+ &lsi->actions, lsi->meter_groups);
build_arp_resolve_flows_for_lrouter_port(op, lsi->lflows, lsi->ports,
&lsi->match, &lsi->actions);
build_egress_delivery_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
&lsi->actions);
build_dhcpv6_reply_flows_for_lrouter_port(op, lsi->lflows, &lsi->match);
build_ipv6_input_flows_for_lrouter_port(op, lsi->lflows,
- &lsi->match, &lsi->actions);
+ &lsi->match, &lsi->actions,
+ lsi->meter_groups);
build_lrouter_ipv4_ip_input(op, lsi->lflows,
- &lsi->match, &lsi->actions);
+ &lsi->match, &lsi->actions, lsi->meter_groups);
build_lrouter_force_snat_flows_op(op, lsi->lflows, &lsi->match,
&lsi->actions);
}
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 384c7ebc9..c1ffa586c 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -414,6 +414,9 @@
<column name="meters" key="bfd">
Rate limiting meter for BFD packets.
</column>
+ <column name="meters" key="reject">
+ Rate limiting meter for packets that trigger a reject action
+ </column>
</table>
<table name="Logical_Switch" title="L2 logical switch">
diff --git a/tests/atlocal.in b/tests/atlocal.in
index b5bc0818b..310fd46a5 100644
--- a/tests/atlocal.in
+++ b/tests/atlocal.in
@@ -169,6 +169,9 @@ find_command tcpdump
# Set HAVE_LFTP
find_command lftp
+# Set HAVE_SCAPY
+find_command scapy
+
CURL_OPT="-g -v --max-time 1 --retry 2 --retry-delay 1 --connect-timeout 1"
# Determine whether "diff" supports "normal" diffs. (busybox diff does not.)
diff --git a/tests/ovn.at b/tests/ovn.at
index bc494fcad..a5ed3a64e 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1665,10 +1665,6 @@ reject { };
trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80", protocol = "tcp", load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
encodes as controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63)
-trigger_event(event = "empty_lb_backends", meter="event-elb" vip = "10.0.0.1:80", protocol = "tcp", load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
- formats as trigger_event(event = "empty_lb_backends", meter = "event-elb", vip = "10.0.0.1:80", protocol = "tcp", load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
- encodes as controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63,meter_id=5)
-
# Testing invalid vip results in extra error messages from socket-util.c
trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80", protocol = "aarp", load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
Load balancer protocol 'aarp' is not 'tcp', 'udp', or 'sctp'
@@ -17716,6 +17712,10 @@ AT_CLEANUP
OVN_FOR_EACH_NORTHD([
AT_SETUP([ovn -- controller event])
AT_KEYWORDS([ovn_controller_event])
+
+dnl This test is not suported by ovn-northd-ddlog yet.
+AT_SKIP_IF([test NORTHD_TYPE = ovn-northd-ddlog && test "$RUN_ANYWAY" != yes])
+
ovn_start
# Create hypervisors hv[12].
@@ -17779,6 +17779,7 @@ ovn-nbctl ls-lb-add sw0 lb2
uuid_lb2=$(ovn-nbctl --bare --columns=_uuid find load_balancer name=lb2)
ovn-nbctl --wait=hv meter-add event-elb drop 100 pktps 10
+ovn-nbctl --wait=hv ls-copp-add sw0 event-elb event-elb
OVN_POPULATE_ARP
wait_for_ports_up
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 1b8bb3803..c4ca42a4a 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -6371,3 +6371,141 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
/connection dropped.*/d"])
AT_CLEANUP
])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([ovn -- CoPP])
+AT_SKIP_IF([test $HAVE_TCPDUMP = no])
+AT_SKIP_IF([test $HAVE_SCAPY = no])
+AT_KEYWORDS([ovn-copp])
+
+dnl This test is not suported by ovn-northd-ddlog yet.
+AT_SKIP_IF([test NORTHD_TYPE = ovn-northd-ddlog && test "$RUN_ANYWAY" != yes])
+
+ovn_start
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_BR([br-int])
+ADD_BR([br-ext])
+
+check ovs-ofctl add-flow br-ext action=normal
+# Set external-ids in br-int needed for ovn-controller
+check ovs-vsctl \
+ -- set Open_vSwitch . external-ids:system-id=hv1 \
+ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
+ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
+ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
+
+# Start ovn-controller
+start_daemon ovn-controller
+
+check ovn-nbctl lr-add R1
+check ovn-nbctl ls-add sw0
+check ovn-nbctl ls-add public
+
+check ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24
+check ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24 1000::a/64 \
+ -- lrp-set-gateway-chassis rp-public hv1
+
+check ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \
+ type=router options:router-port=rp-sw0 \
+ -- lsp-set-addresses sw0-rp router
+
+check ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port public-rp \
+ type=router options:router-port=rp-public \
+ -- lsp-set-addresses public-rp router
+
+ADD_NAMESPACES(sw01)
+ADD_VETH(sw01, sw01, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
+ "192.168.1.1")
+check ovn-nbctl lsp-add sw0 sw01 \
+ -- lsp-set-addresses sw01 "f0:00:00:01:02:03 192.168.1.2"
+
+ADD_NAMESPACES(server)
+NS_CHECK_EXEC([server], [ip link set dev lo up])
+ADD_VETH(s1, server, br-ext, "172.16.1.50/24", "f0:00:00:01:02:05", \
+ "172.16.1.1")
+
+AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext])
+check ovn-nbctl lsp-add public public1 \
+ -- lsp-set-addresses public1 unknown \
+ -- lsp-set-type public1 localnet \
+ -- lsp-set-options public1 network_name=phynet
+
+NS_EXEC([sw01], [tcpdump -n -i sw01 icmp -Q in > reject.pcap &])
+check ovn-nbctl meter-add acl-meter drop 1 pktps 0
+check ovn-nbctl --wait=hv ls-copp-add sw0 reject acl-meter
+check ovn-nbctl acl-add sw0 from-lport 1002 'inport == "sw01" && ip && udp' reject
+
+AT_CHECK([ovn-nbctl ls-copp-list sw0], [0], [dnl
+reject: acl-meter
+])
+
+ip netns exec sw01 scapy -H <<-EOF
+p = IP(src="192.168.1.2", dst="192.168.1.1")/ UDP(dport = 12345) / Raw(b"X"*64)
+send (p, iface='sw01', loop = 0, verbose = 0, count = 20)
+EOF
+
+sleep 2
+kill $(pidof tcpdump)
+
+# 1pps + 1 burst size
+OVS_WAIT_UNTIL([
+ n_reject=$(grep unreachable reject.pcap | wc -l)
+ test "${n_reject}" = "2"
+])
+
+rm -f reject.pcap
+NS_EXEC([sw01], [tcpdump -n -i sw01 icmp -Q in > reject.pcap &])
+check ovn-nbctl --wait=hv ls-copp-del sw0 reject
+
+ip netns exec sw01 scapy -H <<-EOF
+p = IP(src="192.168.1.2", dst="192.168.1.1")/ UDP(dport = 12345) / Raw(b"X"*64)
+send (p, iface='sw01', loop = 0, verbose = 0, count = 20)
+EOF
+
+sleep 2
+kill $(pidof tcpdump)
+
+OVS_WAIT_UNTIL([
+ n_reject=$(grep unreachable reject.pcap | wc -l)
+ test "${n_reject}" = "20"
+])
+
+NS_EXEC([server], [tcpdump -n -i s1 arp[[24:4]]=0xac100164 > arp.pcap &])
+check ovn-nbctl meter-add arp-meter drop 1 pktps 0
+check ovn-nbctl --wait=hv lr-copp-add R1 arp-resolve arp-meter
+AT_CHECK([ovn-nbctl lr-copp-list R1], [0], [dnl
+arp-resolve: arp-meter
+])
+
+ip netns exec sw01 scapy -H <<-EOF
+p = IP(src="192.168.1.2", dst="172.16.1.100")/ TCP(dport = 80, flags="S") / Raw(b"X"*64)
+send (p, iface='sw01', loop = 0, verbose = 0, count = 100)
+EOF
+
+sleep 2
+kill $(pidof tcpdump)
+
+# 1pps + 1 burst size
+OVS_WAIT_UNTIL([
+ n_arp=$(grep ARP arp.pcap | wc -l)
+ test "${n_arp}" = "2"
+])
+
+kill $(pidof ovn-controller)
+
+as ovn-sb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as ovn-nb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as northd
+OVS_APP_EXIT_AND_WAIT([ovn-northd])
+
+as
+OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d
+/.*terminating with signal 15.*/d"])
+AT_CLEANUP
+])
diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml
index 101849911..987797860 100644
--- a/utilities/ovn-nbctl.8.xml
+++ b/utilities/ovn-nbctl.8.xml
@@ -1466,6 +1466,9 @@
<li>packets that need to be replied to with ICMP Errors</li>
<li>packets that need to be replied to with TCP RST</li>
<li>packets that need to be replied to with DHCP_OPTS</li>
+ <li>packets that trigger a reject action</li>
+ <li>packets that trigger a SCTP abort action</li>
+ <li>controller_events</li>
<li>BFD</li>
</ul>
</p>
--
2.31.1
More information about the dev
mailing list