On 29/04/2021 18:04, Lorenzo Bianconi wrote: > From: Dumitru Ceara <[email protected]> > > 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 > - BFD > Add reject?
Do you need to add event-elb? > Co-authored-by: Lorenzo Bianconi <[email protected]> > Signed-off-by: Lorenzo Bianconi <[email protected]> > Signed-off-by: Dumitru Ceara <[email protected]> > --- > lib/copp.c | 1 + > lib/copp.h | 1 + > northd/ovn-northd.c | 451 ++++++++++++++++++++++++-------------- > ovn-nb.xml | 3 + > tests/atlocal.in | 3 + > tests/system-ovn.at | 119 ++++++++++ > utilities/ovn-nbctl.8.xml | 1 + > 7 files changed, 417 insertions(+), 162 deletions(-) > > diff --git a/lib/copp.c b/lib/copp.c > index ac53a1094..7713046e5 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 82581e7e4..826fe987e 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, If it is easy to do, you should merge the reject meter addition into the previous patch as I think that is where it actually belongs. > COPP_PROTO_MAX, > COPP_PROTO_INVALID = COPP_PROTO_MAX, > }; > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > index 2e9c7de22..93b431f4c 100644 > --- a/northd/ovn-northd.c > +++ b/northd/ovn-northd.c > @@ -3328,11 +3328,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; > > @@ -3384,6 +3384,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 > @@ -4174,9 +4175,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(struct hmap *lflows, struct ovn_datapath *od, > @@ -5429,9 +5435,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); > @@ -5938,7 +5947,7 @@ build_lb(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) > { > for (size_t i = 0; i < lb->n_vips; i++) { > struct ovn_lb_vip *lb_vip = &lb->vips[i]; > @@ -5979,21 +5988,25 @@ 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); > + } > > struct ds match = DS_EMPTY_INITIALIZER; > 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(&match); > @@ -6002,7 +6015,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. */ > @@ -6072,7 +6086,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); > } > } > > @@ -6603,6 +6617,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; > @@ -6626,11 +6641,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 > @@ -6650,11 +6668,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 > @@ -6688,6 +6709,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; > @@ -6710,11 +6732,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 */ > @@ -6853,7 +6878,7 @@ build_lswitch_lflows_pre_acl_and_acl(struct > ovn_datapath *od, > build_acls(od, lflows, port_groups, meter_groups); > build_qos(od, lflows); > build_lb(od, lflows); > - build_stateful(od, lflows, lbs); > + build_stateful(od, lflows, lbs, meter_groups); > build_lb_hairpin(od, lflows); > } > } > @@ -6909,6 +6934,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) > { > @@ -7050,11 +7076,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). */ > @@ -7132,7 +7161,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)) { > @@ -7161,17 +7191,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); > } > } > } > @@ -7201,13 +7231,19 @@ 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_add_ctrl(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)); Why do you add the same flow twice but one with a meter instead of modifying the flow above? > 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;"; > @@ -7244,7 +7280,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) { > > @@ -7265,12 +7302,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. > @@ -8650,23 +8691,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. */ > @@ -8792,8 +8839,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); > @@ -8858,7 +8905,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); > @@ -9097,7 +9144,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; > @@ -9119,6 +9166,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 { " > @@ -9135,11 +9184,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); > } > @@ -9147,7 +9198,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; > @@ -9157,7 +9209,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, > @@ -9169,7 +9221,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; > @@ -9212,12 +9265,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, > @@ -9390,7 +9443,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; > @@ -9409,9 +9463,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); > @@ -9426,9 +9482,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); > @@ -9508,7 +9566,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) { > > @@ -9588,14 +9647,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_add_ctrl(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_add_ctrl(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_add_ctrl(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)); > } > > } > @@ -9670,7 +9735,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; > @@ -9763,9 +9829,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 && " > @@ -10388,7 +10457,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) { > > @@ -10450,10 +10520,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) { > @@ -10479,10 +10553,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_); > } > } > } > @@ -10537,7 +10615,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++) { > @@ -10574,26 +10653,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_add_ctrl(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_add_ctrl(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;"); > } > } > @@ -10724,7 +10810,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 > @@ -10767,7 +10854,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 */ > @@ -10782,9 +10869,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, > @@ -10809,9 +10900,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, > @@ -10824,9 +10919,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_); > } > } > > @@ -10857,9 +10956,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_); > } > } > > @@ -10867,7 +10969,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) { > > @@ -10893,7 +10996,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. */ > @@ -10908,7 +11011,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); > } > } > } > @@ -10917,7 +11020,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. */ > @@ -10955,7 +11059,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++) { > @@ -10975,9 +11079,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 > @@ -11051,7 +11158,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); > } > > sset_destroy(&all_ips_v4); > @@ -11072,9 +11180,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, > @@ -11084,9 +11196,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, > @@ -11111,9 +11227,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_); > } > } > > @@ -11157,7 +11277,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. */ > @@ -11172,7 +11293,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); > } > } > } > @@ -11853,15 +11975,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); > @@ -11870,13 +11993,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); > } > @@ -11896,9 +12020,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); > @@ -11912,16 +12038,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 0f03a12f2..7695514a5 100644 > --- a/ovn-nb.xml > +++ b/ovn-nb.xml > @@ -399,6 +399,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/system-ovn.at b/tests/system-ovn.at > index b6c679907..8a9cbde98 100644 > --- a/tests/system-ovn.at > +++ b/tests/system-ovn.at > @@ -5890,3 +5890,122 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d > /.*terminating with signal 15.*/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]) > + > +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") > +NS_CHECK_EXEC([server], [ip addr add 1000::b/64 dev s1]) Why do you add this IPv6 address here? > + > +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_CHECK_EXEC([sw01], [tcpdump -nni 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" > +]) > + > +NS_CHECK_EXEC([server], [tcpdump -nni 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 Did you test this with the meters disabled? Does it behave as expected? > +]) > diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml > index 6c95e8104..5f5f71015 100644 > --- a/utilities/ovn-nbctl.8.xml > +++ b/utilities/ovn-nbctl.8.xml > @@ -1151,6 +1151,7 @@ > <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>BFD</li> > </ul> > </p> > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
