Message ID | e011d1a6431e061690dc168a0a88f52585e90985.1619260398.git.lorenzo.bianconi@redhat.com |
---|---|
State | Superseded |
Headers | show |
Series | respin CoPP series | expand |
On 24/04/2021 11:39, Lorenzo Bianconi wrote: > From: Dumitru Ceara <dceara@redhat.com> > > Add a new 'controller_meter' column to OVN Southbound Logical_Flow > table. This stores an optional string which should correspond to > the Meter that must be used for rate limiting controller actions > generated by packets hitting the flow. > > Add a new 'ofctrl_add_flow_meter' function to create a new 'ovn_flow' > with an attached controller meter. The function names sounds like you are adding a flow meter rather than a metred flow. Maybe you could change the name to ofctrl_add_metred_flow() or ofctrl_add_flow_metred() > > Change ofctrl_check_and_add_flow to allow specifying a meter ID for > packets that are punted to controller. > > Change consider_logical_flow to parse controller_meter from the logical > flow and use it when building openflow entries. > > Add a new 'ctrl_meter_id' field to 'struct ovnact_encode_params' to be > used when encoding controller actions from logical flow actions. > > Co-authored-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> > Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> > Signed-off-by: Dumitru Ceara <dceara@redhat.com> > --- > controller/lflow.c | 38 ++++++++++++++++++++++--- > controller/ofctrl.c | 36 +++++++++++++++++------ > controller/ofctrl.h | 13 +++++++-- > controller/physical.c | 3 +- > include/ovn/actions.h | 2 ++ > lib/actions.c | 66 +++++++++++++++++++++++-------------------- > ovn-sb.ovsschema | 6 ++-- > ovn-sb.xml | 6 ++++ > 8 files changed, 121 insertions(+), 49 deletions(-) > > diff --git a/controller/lflow.c b/controller/lflow.c > index 680b8cca1..684fc43e6 100644 > --- a/controller/lflow.c > +++ b/controller/lflow.c > @@ -557,6 +557,26 @@ update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t n_conjs) > return false; > } > > +static void > +lflow_parse_ctrl_meter(const struct sbrec_logical_flow *lflow, > + struct ovn_extend_table *meter_table, > + uint32_t *meter_id) > +{ You might need to assert() that 'meter_id' is not NULL > + *meter_id = NX_CTLR_NO_METER; > + > + if (lflow->controller_meter) { > + *meter_id = ovn_extend_table_assign_id(meter_table, > + lflow->controller_meter, > + lflow->header_.uuid); > + if (*meter_id == EXT_TABLE_ID_INVALID) { > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); > + VLOG_WARN_RL(&rl, "Unable to assign id for meter: %s", > + lflow->controller_meter); > + return; > + } > + } > +} > + > static void > add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > const struct sbrec_datapath_binding *dp, > @@ -572,6 +592,13 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > .dp = dp, > }; > > + /* Parse any meter to be used if this flow should punt packets to > + * controller. > + */ > + uint32_t ctrl_meter_id = NX_CTLR_NO_METER; > + lflow_parse_ctrl_meter(lflow, l_ctx_out->meter_table, > + &ctrl_meter_id); > + > /* Encode OVN logical actions into OpenFlow. */ > uint64_t ofpacts_stub[1024 / 8]; > struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); > @@ -595,6 +622,7 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > .ct_snat_vip_ptable = OFTABLE_CT_SNAT_FOR_VIP, > .fdb_ptable = OFTABLE_GET_FDB, > .fdb_lookup_ptable = OFTABLE_LOOKUP_FDB, > + .ctrl_meter_id = ctrl_meter_id, > }; > ovnacts_encode(ovnacts->data, ovnacts->size, &ep, &ofpacts); > > @@ -621,9 +649,10 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > } > } > if (!m->n) { > - ofctrl_add_flow(l_ctx_out->flow_table, ptable, lflow->priority, > - lflow->header_.uuid.parts[0], &m->match, &ofpacts, > - &lflow->header_.uuid); > + ofctrl_add_flow_meter(l_ctx_out->flow_table, ptable, lflow->priority, > + lflow->header_.uuid.parts[0], &m->match, > + &ofpacts, &lflow->header_.uuid, > + ctrl_meter_id); > } else { > uint64_t conj_stubs[64 / 8]; > struct ofpbuf conj; > @@ -641,7 +670,8 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > > ofctrl_add_or_append_flow(l_ctx_out->flow_table, ptable, > lflow->priority, 0, > - &m->match, &conj, &lflow->header_.uuid); > + &m->match, &conj, &lflow->header_.uuid, > + ctrl_meter_id); > ofpbuf_uninit(&conj); > } > } > diff --git a/controller/ofctrl.c b/controller/ofctrl.c > index c29c3d180..126df7741 100644 > --- a/controller/ofctrl.c > +++ b/controller/ofctrl.c > @@ -66,6 +66,7 @@ struct ovn_flow { > struct ofpact *ofpacts; > size_t ofpacts_len; > uint64_t cookie; > + uint32_t ctrl_meter_id; /* Meter to be used for controller actions. */ > }; > > /* A desired flow, in struct ovn_desired_flow_table, calculated by the > @@ -220,7 +221,8 @@ static struct desired_flow *desired_flow_alloc( > uint16_t priority, > uint64_t cookie, > const struct match *match, > - const struct ofpbuf *actions); > + const struct ofpbuf *actions, > + uint32_t meter_id); > static struct desired_flow *desired_flow_lookup( > struct ovn_desired_flow_table *, > const struct ovn_flow *target); > @@ -1025,10 +1027,10 @@ ofctrl_check_and_add_flow(struct ovn_desired_flow_table *flow_table, Can you update the comment describing this function? The comment doesn't include the meter parameter. > uint64_t cookie, const struct match *match, > const struct ofpbuf *actions, > const struct uuid *sb_uuid, > - bool log_duplicate_flow) > + uint32_t meter_id, bool log_duplicate_flow) > { > struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie, > - match, actions); > + match, actions, meter_id); > > if (desired_flow_lookup_check_uuid(flow_table, &f->flow, sb_uuid)) { > if (log_duplicate_flow) { > @@ -1055,9 +1057,19 @@ ofctrl_add_flow(struct ovn_desired_flow_table *desired_flows, > uint8_t table_id, uint16_t priority, uint64_t cookie, > const struct match *match, const struct ofpbuf *actions, > const struct uuid *sb_uuid) > +{ > + ofctrl_add_flow_meter(desired_flows, table_id, priority, cookie, > + match, actions, sb_uuid, NX_CTLR_NO_METER); > +} > + > +void > +ofctrl_add_flow_meter(struct ovn_desired_flow_table *desired_flows, > + uint8_t table_id, uint16_t priority, uint64_t cookie, > + const struct match *match, const struct ofpbuf *actions, > + const struct uuid *sb_uuid, uint32_t meter_id) > { > ofctrl_check_and_add_flow(desired_flows, table_id, priority, cookie, > - match, actions, sb_uuid, true); > + match, actions, sb_uuid, meter_id, true); > } > > /* Either add a new flow, or append actions on an existing flow. If the > @@ -1068,12 +1080,14 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, > uint8_t table_id, uint16_t priority, uint64_t cookie, > const struct match *match, > const struct ofpbuf *actions, > - const struct uuid *sb_uuid) > + const struct uuid *sb_uuid, > + uint32_t meter_id) > { > struct desired_flow *existing; > struct desired_flow *f; > > - f = desired_flow_alloc(table_id, priority, cookie, match, actions); > + f = desired_flow_alloc(table_id, priority, cookie, match, actions, > + meter_id); > existing = desired_flow_lookup_conjunctive(desired_flows, &f->flow); > if (existing) { > /* There's already a flow with this particular match and action > @@ -1278,7 +1292,7 @@ ofctrl_flood_remove_flows(struct ovn_desired_flow_table *flow_table, > static void > ovn_flow_init(struct ovn_flow *f, uint8_t table_id, uint16_t priority, > uint64_t cookie, const struct match *match, > - const struct ofpbuf *actions) > + const struct ofpbuf *actions, uint32_t meter_id) > { > f->table_id = table_id; > f->priority = priority; > @@ -1287,11 +1301,13 @@ ovn_flow_init(struct ovn_flow *f, uint8_t table_id, uint16_t priority, > f->ofpacts_len = actions->size; > f->hash = ovn_flow_match_hash(f); > f->cookie = cookie; > + f->ctrl_meter_id = meter_id; > } > > static struct desired_flow * > desired_flow_alloc(uint8_t table_id, uint16_t priority, uint64_t cookie, > - const struct match *match, const struct ofpbuf *actions) > + const struct match *match, const struct ofpbuf *actions, > + uint32_t meter_id) > { > struct desired_flow *f = xmalloc(sizeof *f); > ovs_list_init(&f->references); > @@ -1300,7 +1316,7 @@ desired_flow_alloc(uint8_t table_id, uint16_t priority, uint64_t cookie, > ovs_list_init(&f->track_list_node); > f->installed_flow = NULL; > f->is_deleted = false; > - ovn_flow_init(&f->flow, table_id, priority, cookie, match, actions); > + ovn_flow_init(&f->flow, table_id, priority, cookie, match, actions, meter_id); > > return f; > } > @@ -1326,6 +1342,7 @@ installed_flow_dup(struct desired_flow *src) > dst->flow.ofpacts_len = src->flow.ofpacts_len; > dst->flow.hash = src->flow.hash; > dst->flow.cookie = src->flow.cookie; > + dst->flow.ctrl_meter_id = src->flow.ctrl_meter_id; > return dst; > } > > @@ -1352,6 +1369,7 @@ desired_flow_lookup__(struct ovn_desired_flow_table *flow_table, > struct ovn_flow *f = &d->flow; > if (f->table_id == target->table_id > && f->priority == target->priority > + && f->ctrl_meter_id == target->ctrl_meter_id > && minimatch_equal(&f->match, &target->match)) { > > if (!match_cb || match_cb(d, arg)) { > diff --git a/controller/ofctrl.h b/controller/ofctrl.h > index 88769566a..db374d4e8 100644 > --- a/controller/ofctrl.h > +++ b/controller/ofctrl.h > @@ -78,7 +78,15 @@ void ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, > uint8_t table_id, uint16_t priority, > uint64_t cookie, const struct match *match, > const struct ofpbuf *actions, > - const struct uuid *sb_uuid); > + const struct uuid *sb_uuid, > + uint32_t meter_id); > + > +void ofctrl_add_flow_meter(struct ovn_desired_flow_table *desired_flows, > + uint8_t table_id, uint16_t priority, > + uint64_t cookie, const struct match *match, > + const struct ofpbuf *actions, > + const struct uuid *sb_uuid, > + uint32_t meter_id); Maybe ofctl_add_or_append_flow() should be updated with a metered and un-metered version? This one seems to add a meter, yet the name does not reflect that. > > /* Removes a bundles of flows from the flow table for a specific sb_uuid. The > * flows are removed only if they are not referenced by any other sb_uuid(s). > @@ -112,7 +120,8 @@ void ofctrl_check_and_add_flow(struct ovn_desired_flow_table *, > uint8_t table_id, uint16_t priority, > uint64_t cookie, const struct match *, > const struct ofpbuf *ofpacts, > - const struct uuid *, bool log_duplicate_flow); > + const struct uuid *, uint32_t meter_id, > + bool log_duplicate_flow); > > > bool ofctrl_is_connected(void); > diff --git a/controller/physical.c b/controller/physical.c > index 96c959d18..95f92a85e 100644 > --- a/controller/physical.c > +++ b/controller/physical.c > @@ -858,7 +858,8 @@ put_local_common_flows(uint32_t dp_key, uint32_t port_key, > put_resubmit(OFTABLE_LOG_TO_PHY, ofpacts_p); > put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p)); > ofctrl_check_and_add_flow(flow_table, OFTABLE_SAVE_INPORT, 100, 0, > - &match, ofpacts_p, hc_uuid, false); > + &match, ofpacts_p, hc_uuid, NX_CTLR_NO_METER, > + false); > } > } > > diff --git a/include/ovn/actions.h b/include/ovn/actions.h > index 040213177..ab03df12c 100644 > --- a/include/ovn/actions.h > +++ b/include/ovn/actions.h > @@ -795,6 +795,8 @@ struct ovnact_encode_params { > * 'get_fdb' to resubmit. */ > uint8_t fdb_lookup_ptable; /* OpenFlow table for > * 'lookup_fdb' to resubmit. */ > + uint32_t ctrl_meter_id; /* Meter to be used if the resulting flow > + sends packets to controller. */ > }; > > void ovnacts_encode(const struct ovnact[], size_t ovnacts_len, > diff --git a/lib/actions.c b/lib/actions.c > index b3433f49e..155b4a45a 100644 > --- a/lib/actions.c > +++ b/lib/actions.c > @@ -105,10 +105,10 @@ encode_finish_controller_op(size_t ofs, struct ofpbuf *ofpacts) > } > > static void > -encode_controller_op(enum action_opcode opcode, struct ofpbuf *ofpacts) > +encode_controller_op(enum action_opcode opcode, uint32_t meter_id, > + struct ofpbuf *ofpacts) > { > - size_t ofs = encode_start_controller_op(opcode, false, NX_CTLR_NO_METER, > - ofpacts); > + size_t ofs = encode_start_controller_op(opcode, false, meter_id, ofpacts); > encode_finish_controller_op(ofs, ofpacts); > } > > @@ -1647,7 +1647,7 @@ encode_nested_actions(const struct ovnact_nest *on, > * packet to ARP or NA and then send the packet and actions back to the > * switch inside an OFPT_PACKET_OUT message. */ > size_t oc_offset = encode_start_controller_op(opcode, false, > - NX_CTLR_NO_METER, ofpacts); > + ep->ctrl_meter_id, ofpacts); > ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size, > ofpacts, OFP15_VERSION); > encode_finish_controller_op(oc_offset, ofpacts); > @@ -1698,10 +1698,10 @@ encode_ICMP6_ERROR(const struct ovnact_nest *on, > > static void > encode_IGMP(const struct ovnact_null *a OVS_UNUSED, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > - encode_controller_op(ACTION_OPCODE_IGMP, ofpacts); > + encode_controller_op(ACTION_OPCODE_IGMP, ep->ctrl_meter_id, ofpacts); > } > > static void > @@ -1943,6 +1943,7 @@ format_PUT_ND(const struct ovnact_put_mac_bind *put_mac, struct ds *s) > > static void > encode_put_mac(const struct ovnact_put_mac_bind *put_mac, > + const struct ovnact_encode_params *ep, > enum mf_field_id ip_field, enum action_opcode opcode, > struct ofpbuf *ofpacts) > { > @@ -1952,24 +1953,24 @@ encode_put_mac(const struct ovnact_put_mac_bind *put_mac, > { expr_resolve_field(&put_mac->mac), MFF_ETH_SRC } > }; > encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > - encode_controller_op(opcode, ofpacts); > + encode_controller_op(opcode, ep->ctrl_meter_id, ofpacts); > encode_restore_args(args, ARRAY_SIZE(args), ofpacts); > } > > static void > encode_PUT_ARP(const struct ovnact_put_mac_bind *put_mac, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > - encode_put_mac(put_mac, MFF_REG0, ACTION_OPCODE_PUT_ARP, ofpacts); > + encode_put_mac(put_mac, ep, MFF_REG0, ACTION_OPCODE_PUT_ARP, ofpacts); > } > > static void > encode_PUT_ND(const struct ovnact_put_mac_bind *put_mac, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > - encode_put_mac(put_mac, MFF_XXREG0, ACTION_OPCODE_PUT_ND, ofpacts); > + encode_put_mac(put_mac, ep, MFF_XXREG0, ACTION_OPCODE_PUT_ND, ofpacts); > } > > static void > @@ -2670,13 +2671,13 @@ encode_put_dhcpv6_option(const struct ovnact_gen_option *o, > > static void > encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts *pdo, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > struct mf_subfield dst = expr_resolve_field(&pdo->dst); > > size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_PUT_DHCP_OPTS, > - true, NX_CTLR_NO_METER, > + true, ep->ctrl_meter_id, > ofpacts); > nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); > ovs_be32 ofs = htonl(dst.ofs); > @@ -2723,13 +2724,13 @@ encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts *pdo, > > static void > encode_PUT_DHCPV6_OPTS(const struct ovnact_put_opts *pdo, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > struct mf_subfield dst = expr_resolve_field(&pdo->dst); > > size_t oc_offset = encode_start_controller_op( > - ACTION_OPCODE_PUT_DHCPV6_OPTS, true, NX_CTLR_NO_METER, ofpacts); > + ACTION_OPCODE_PUT_DHCPV6_OPTS, true, ep->ctrl_meter_id, ofpacts); > nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); > ovs_be32 ofs = htonl(dst.ofs); > ofpbuf_put(ofpacts, &ofs, sizeof ofs); > @@ -2756,10 +2757,11 @@ format_DHCP6_REPLY(const struct ovnact_null *a OVS_UNUSED, struct ds *s) > > static void > encode_DHCP6_REPLY(const struct ovnact_null *a OVS_UNUSED, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > - encode_controller_op(ACTION_OPCODE_DHCP6_SERVER, ofpacts); > + encode_controller_op(ACTION_OPCODE_DHCP6_SERVER, ep->ctrl_meter_id, > + ofpacts); > } > > static void > @@ -2770,10 +2772,11 @@ format_BFD_MSG(const struct ovnact_null *a OVS_UNUSED, struct ds *s) > > static void > encode_BFD_MSG(const struct ovnact_null *a OVS_UNUSED, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > - encode_controller_op(ACTION_OPCODE_BFD_MSG, ofpacts); > + encode_controller_op(ACTION_OPCODE_BFD_MSG, ep->ctrl_meter_id, > + ofpacts); > } > > static void > @@ -2868,13 +2871,13 @@ format_DNS_LOOKUP(const struct ovnact_result *dl, struct ds *s) > > static void > encode_DNS_LOOKUP(const struct ovnact_result *dl, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > struct mf_subfield dst = expr_resolve_field(&dl->dst); > > size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_DNS_LOOKUP, > - true, NX_CTLR_NO_METER, > + true, ep->ctrl_meter_id, > ofpacts); > nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); > ovs_be32 ofs = htonl(dst.ofs); > @@ -3052,13 +3055,13 @@ encode_put_nd_ra_option(const struct ovnact_gen_option *o, > > static void > encode_PUT_ND_RA_OPTS(const struct ovnact_put_opts *po, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > struct mf_subfield dst = expr_resolve_field(&po->dst); > > size_t oc_offset = encode_start_controller_op( > - ACTION_OPCODE_PUT_ND_RA_OPTS, true, NX_CTLR_NO_METER, ofpacts); > + ACTION_OPCODE_PUT_ND_RA_OPTS, true, ep->ctrl_meter_id, ofpacts); > nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); > ovs_be32 ofs = htonl(dst.ofs); > ofpbuf_put(ofpacts, &ofs, sizeof ofs); > @@ -3341,7 +3344,7 @@ format_OVNFIELD_LOAD(const struct ovnact_load *load , struct ds *s) > > static void > encode_OVNFIELD_LOAD(const struct ovnact_load *load, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > const struct ovn_field *f = ovn_field_from_name(load->dst.symbol->name); > @@ -3349,7 +3352,7 @@ encode_OVNFIELD_LOAD(const struct ovnact_load *load, > case OVN_ICMP4_FRAG_MTU: { > size_t oc_offset = encode_start_controller_op( > ACTION_OPCODE_PUT_ICMP4_FRAG_MTU, true, > - NX_CTLR_NO_METER, ofpacts); > + ep->ctrl_meter_id, ofpacts); > ofpbuf_put(ofpacts, &load->imm.value.be16_int, sizeof(ovs_be16)); > encode_finish_controller_op(oc_offset, ofpacts); > break; > @@ -3357,7 +3360,7 @@ encode_OVNFIELD_LOAD(const struct ovnact_load *load, > case OVN_ICMP6_FRAG_MTU: { > size_t oc_offset = encode_start_controller_op( > ACTION_OPCODE_PUT_ICMP6_FRAG_MTU, true, > - NX_CTLR_NO_METER, ofpacts); > + ep->ctrl_meter_id, ofpacts); > ofpbuf_put(ofpacts, &load->imm.value.be32_int, sizeof(ovs_be32)); > encode_finish_controller_op(oc_offset, ofpacts); > break; > @@ -3461,7 +3464,7 @@ encode_BIND_VPORT(const struct ovnact_bind_vport *vp, > }; > encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_BIND_VPORT, > - false, NX_CTLR_NO_METER, > + false, ep->ctrl_meter_id, > ofpacts); > ovs_be32 vp_key = htonl(vport_key); > ofpbuf_put(ofpacts, &vp_key, sizeof(ovs_be32)); > @@ -3499,14 +3502,15 @@ format_HANDLE_SVC_CHECK(const struct ovnact_handle_svc_check *svc_chk, > > static void > encode_HANDLE_SVC_CHECK(const struct ovnact_handle_svc_check *svc_chk, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > const struct arg args[] = { > { expr_resolve_field(&svc_chk->port), MFF_LOG_INPORT }, > }; > encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > - encode_controller_op(ACTION_OPCODE_HANDLE_SVC_CHECK, ofpacts); > + encode_controller_op(ACTION_OPCODE_HANDLE_SVC_CHECK, ep->ctrl_meter_id, > + ofpacts); > encode_restore_args(args, ARRAY_SIZE(args), ofpacts); > } > > @@ -3755,7 +3759,7 @@ format_PUT_FDB(const struct ovnact_put_fdb *put_fdb, struct ds *s) > > static void > encode_PUT_FDB(const struct ovnact_put_fdb *put_fdb, > - const struct ovnact_encode_params *ep OVS_UNUSED, > + const struct ovnact_encode_params *ep, > struct ofpbuf *ofpacts) > { > const struct arg args[] = { > @@ -3763,7 +3767,7 @@ encode_PUT_FDB(const struct ovnact_put_fdb *put_fdb, > { expr_resolve_field(&put_fdb->mac), MFF_ETH_SRC } > }; > encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > - encode_controller_op(ACTION_OPCODE_PUT_FDB, ofpacts); > + encode_controller_op(ACTION_OPCODE_PUT_FDB, ep->ctrl_meter_id, ofpacts); > encode_restore_args(args, ARRAY_SIZE(args), ofpacts); > } > > diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema > index 205a30a37..609699475 100644 > --- a/ovn-sb.ovsschema > +++ b/ovn-sb.ovsschema > @@ -1,7 +1,7 @@ > { > "name": "OVN_Southbound", > - "version": "20.17.0", > - "cksum": "669123379 26536", > + "version": "20.18.0", > + "cksum": "3870294693 26668", > "tables": { > "SB_Global": { > "columns": { > @@ -109,6 +109,8 @@ > "maxInteger": 65535}}}, > "match": {"type": "string"}, > "actions": {"type": "string"}, > + "controller_meter": {"type": {"key": {"type": "string"}, > + "min": 0, "max": 1}}, > "external_ids": { > "type": {"key": "string", "value": "string", > "min": 0, "max": "unlimited"}}}, > diff --git a/ovn-sb.xml b/ovn-sb.xml > index 258a12b4e..57c522db3 100644 > --- a/ovn-sb.xml > +++ b/ovn-sb.xml > @@ -2441,6 +2441,12 @@ tcp.flags = RST; > </dl> > </column> > > + <column name="controller_meter"> > + The name of the meter in table <ref table="Meter"/> to be used for > + all packets that the logical flow might send to > + <code>ovn-controller</code>. > + </column> > + > <column name="external_ids" key="stage-name"> > Human-readable name for this flow's stage in the pipeline. > </column> >
> On 24/04/2021 11:39, Lorenzo Bianconi wrote: > > From: Dumitru Ceara <dceara@redhat.com> > > > > Add a new 'controller_meter' column to OVN Southbound Logical_Flow > > table. This stores an optional string which should correspond to > > the Meter that must be used for rate limiting controller actions > > generated by packets hitting the flow. > > > > Add a new 'ofctrl_add_flow_meter' function to create a new 'ovn_flow' > > with an attached controller meter. > > The function names sounds like you are adding a flow meter rather than a > metred flow. Maybe you could change the name to > > ofctrl_add_metred_flow() or > ofctrl_add_flow_metred() Hi Mark, thx for the review. ack I will fix it posting a formal series. > > > > Change ofctrl_check_and_add_flow to allow specifying a meter ID for > > packets that are punted to controller. > > > > Change consider_logical_flow to parse controller_meter from the logical > > flow and use it when building openflow entries. > > > > Add a new 'ctrl_meter_id' field to 'struct ovnact_encode_params' to be > > used when encoding controller actions from logical flow actions. > > > > Co-authored-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> > > Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> > > Signed-off-by: Dumitru Ceara <dceara@redhat.com> > > --- > > controller/lflow.c | 38 ++++++++++++++++++++++--- > > controller/ofctrl.c | 36 +++++++++++++++++------ > > controller/ofctrl.h | 13 +++++++-- > > controller/physical.c | 3 +- > > include/ovn/actions.h | 2 ++ > > lib/actions.c | 66 +++++++++++++++++++++++-------------------- > > ovn-sb.ovsschema | 6 ++-- > > ovn-sb.xml | 6 ++++ > > 8 files changed, 121 insertions(+), 49 deletions(-) > > > > diff --git a/controller/lflow.c b/controller/lflow.c > > index 680b8cca1..684fc43e6 100644 > > --- a/controller/lflow.c > > +++ b/controller/lflow.c > > @@ -557,6 +557,26 @@ update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t n_conjs) > > return false; > > } > > > > +static void > > +lflow_parse_ctrl_meter(const struct sbrec_logical_flow *lflow, > > + struct ovn_extend_table *meter_table, > > + uint32_t *meter_id) > > +{ > > You might need to assert() that 'meter_id' is not NULL ack, I will add it > > > + *meter_id = NX_CTLR_NO_METER; > > + > > + if (lflow->controller_meter) { > > + *meter_id = ovn_extend_table_assign_id(meter_table, > > + lflow->controller_meter, > > + lflow->header_.uuid); > > + if (*meter_id == EXT_TABLE_ID_INVALID) { > > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); > > + VLOG_WARN_RL(&rl, "Unable to assign id for meter: %s", > > + lflow->controller_meter); > > + return; > > + } > > + } > > +} > > + > > static void > > add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > > const struct sbrec_datapath_binding *dp, > > @@ -572,6 +592,13 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > > .dp = dp, > > }; > > > > + /* Parse any meter to be used if this flow should punt packets to > > + * controller. > > + */ > > + uint32_t ctrl_meter_id = NX_CTLR_NO_METER; > > + lflow_parse_ctrl_meter(lflow, l_ctx_out->meter_table, > > + &ctrl_meter_id); > > + > > /* Encode OVN logical actions into OpenFlow. */ > > uint64_t ofpacts_stub[1024 / 8]; > > struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); > > @@ -595,6 +622,7 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > > .ct_snat_vip_ptable = OFTABLE_CT_SNAT_FOR_VIP, > > .fdb_ptable = OFTABLE_GET_FDB, > > .fdb_lookup_ptable = OFTABLE_LOOKUP_FDB, > > + .ctrl_meter_id = ctrl_meter_id, > > }; > > ovnacts_encode(ovnacts->data, ovnacts->size, &ep, &ofpacts); > > > > @@ -621,9 +649,10 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > > } > > } > > if (!m->n) { > > - ofctrl_add_flow(l_ctx_out->flow_table, ptable, lflow->priority, > > - lflow->header_.uuid.parts[0], &m->match, &ofpacts, > > - &lflow->header_.uuid); > > + ofctrl_add_flow_meter(l_ctx_out->flow_table, ptable, lflow->priority, > > + lflow->header_.uuid.parts[0], &m->match, > > + &ofpacts, &lflow->header_.uuid, > > + ctrl_meter_id); > > } else { > > uint64_t conj_stubs[64 / 8]; > > struct ofpbuf conj; > > @@ -641,7 +670,8 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, > > > > ofctrl_add_or_append_flow(l_ctx_out->flow_table, ptable, > > lflow->priority, 0, > > - &m->match, &conj, &lflow->header_.uuid); > > + &m->match, &conj, &lflow->header_.uuid, > > + ctrl_meter_id); > > ofpbuf_uninit(&conj); > > } > > } > > diff --git a/controller/ofctrl.c b/controller/ofctrl.c > > index c29c3d180..126df7741 100644 > > --- a/controller/ofctrl.c > > +++ b/controller/ofctrl.c > > @@ -66,6 +66,7 @@ struct ovn_flow { > > struct ofpact *ofpacts; > > size_t ofpacts_len; > > uint64_t cookie; > > + uint32_t ctrl_meter_id; /* Meter to be used for controller actions. */ > > }; > > > > /* A desired flow, in struct ovn_desired_flow_table, calculated by the > > @@ -220,7 +221,8 @@ static struct desired_flow *desired_flow_alloc( > > uint16_t priority, > > uint64_t cookie, > > const struct match *match, > > - const struct ofpbuf *actions); > > + const struct ofpbuf *actions, > > + uint32_t meter_id); > > static struct desired_flow *desired_flow_lookup( > > struct ovn_desired_flow_table *, > > const struct ovn_flow *target); > > @@ -1025,10 +1027,10 @@ ofctrl_check_and_add_flow(struct ovn_desired_flow_table *flow_table, > > Can you update the comment describing this function? The comment doesn't > include the meter parameter. ack, I will fix it > > > uint64_t cookie, const struct match *match, > > const struct ofpbuf *actions, > > const struct uuid *sb_uuid, > > - bool log_duplicate_flow) > > + uint32_t meter_id, bool log_duplicate_flow) > > { > > struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie, > > - match, actions); > > + match, actions, meter_id); > > > > if (desired_flow_lookup_check_uuid(flow_table, &f->flow, sb_uuid)) { > > if (log_duplicate_flow) { > > @@ -1055,9 +1057,19 @@ ofctrl_add_flow(struct ovn_desired_flow_table *desired_flows, > > uint8_t table_id, uint16_t priority, uint64_t cookie, > > const struct match *match, const struct ofpbuf *actions, > > const struct uuid *sb_uuid) > > +{ > > + ofctrl_add_flow_meter(desired_flows, table_id, priority, cookie, > > + match, actions, sb_uuid, NX_CTLR_NO_METER); > > +} > > + > > +void > > +ofctrl_add_flow_meter(struct ovn_desired_flow_table *desired_flows, > > + uint8_t table_id, uint16_t priority, uint64_t cookie, > > + const struct match *match, const struct ofpbuf *actions, > > + const struct uuid *sb_uuid, uint32_t meter_id) > > { > > ofctrl_check_and_add_flow(desired_flows, table_id, priority, cookie, > > - match, actions, sb_uuid, true); > > + match, actions, sb_uuid, meter_id, true); > > } > > [...] > > --- a/controller/ofctrl.h > > +++ b/controller/ofctrl.h > > @@ -78,7 +78,15 @@ void ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, > > uint8_t table_id, uint16_t priority, > > uint64_t cookie, const struct match *match, > > const struct ofpbuf *actions, > > - const struct uuid *sb_uuid); > > + const struct uuid *sb_uuid, > > + uint32_t meter_id); > > + > > +void ofctrl_add_flow_meter(struct ovn_desired_flow_table *desired_flows, > > + uint8_t table_id, uint16_t priority, > > + uint64_t cookie, const struct match *match, > > + const struct ofpbuf *actions, > > + const struct uuid *sb_uuid, > > + uint32_t meter_id); > > Maybe ofctl_add_or_append_flow() should be updated with a metered and > un-metered version? This one seems to add a meter, yet the name does not > reflect that. ack, I will fix it according to the name convention Regards, Lorenzo > > > > > /* Removes a bundles of flows from the flow table for a specific sb_uuid. The > > * flows are removed only if they are not referenced by any other sb_uuid(s). > > @@ -112,7 +120,8 @@ void ofctrl_check_and_add_flow(struct ovn_desired_flow_table *, > > uint8_t table_id, uint16_t priority, > > uint64_t cookie, const struct match *, > > const struct ofpbuf *ofpacts, > > - const struct uuid *, bool log_duplicate_flow); > > + const struct uuid *, uint32_t meter_id, > > + bool log_duplicate_flow); > > > > > > bool ofctrl_is_connected(void); > > diff --git a/controller/physical.c b/controller/physical.c > > index 96c959d18..95f92a85e 100644 > > --- a/controller/physical.c > > +++ b/controller/physical.c > > @@ -858,7 +858,8 @@ put_local_common_flows(uint32_t dp_key, uint32_t port_key, > > put_resubmit(OFTABLE_LOG_TO_PHY, ofpacts_p); > > put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p)); > > ofctrl_check_and_add_flow(flow_table, OFTABLE_SAVE_INPORT, 100, 0, > > - &match, ofpacts_p, hc_uuid, false); > > + &match, ofpacts_p, hc_uuid, NX_CTLR_NO_METER, > > + false); > > } > > } > > > > diff --git a/include/ovn/actions.h b/include/ovn/actions.h > > index 040213177..ab03df12c 100644 > > --- a/include/ovn/actions.h > > +++ b/include/ovn/actions.h > > @@ -795,6 +795,8 @@ struct ovnact_encode_params { > > * 'get_fdb' to resubmit. */ > > uint8_t fdb_lookup_ptable; /* OpenFlow table for > > * 'lookup_fdb' to resubmit. */ > > + uint32_t ctrl_meter_id; /* Meter to be used if the resulting flow > > + sends packets to controller. */ > > }; > > > > void ovnacts_encode(const struct ovnact[], size_t ovnacts_len, > > diff --git a/lib/actions.c b/lib/actions.c > > index b3433f49e..155b4a45a 100644 > > --- a/lib/actions.c > > +++ b/lib/actions.c > > @@ -105,10 +105,10 @@ encode_finish_controller_op(size_t ofs, struct ofpbuf *ofpacts) > > } > > > > static void > > -encode_controller_op(enum action_opcode opcode, struct ofpbuf *ofpacts) > > +encode_controller_op(enum action_opcode opcode, uint32_t meter_id, > > + struct ofpbuf *ofpacts) > > { > > - size_t ofs = encode_start_controller_op(opcode, false, NX_CTLR_NO_METER, > > - ofpacts); > > + size_t ofs = encode_start_controller_op(opcode, false, meter_id, ofpacts); > > encode_finish_controller_op(ofs, ofpacts); > > } > > > > @@ -1647,7 +1647,7 @@ encode_nested_actions(const struct ovnact_nest *on, > > * packet to ARP or NA and then send the packet and actions back to the > > * switch inside an OFPT_PACKET_OUT message. */ > > size_t oc_offset = encode_start_controller_op(opcode, false, > > - NX_CTLR_NO_METER, ofpacts); > > + ep->ctrl_meter_id, ofpacts); > > ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size, > > ofpacts, OFP15_VERSION); > > encode_finish_controller_op(oc_offset, ofpacts); > > @@ -1698,10 +1698,10 @@ encode_ICMP6_ERROR(const struct ovnact_nest *on, > > > > static void > > encode_IGMP(const struct ovnact_null *a OVS_UNUSED, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > - encode_controller_op(ACTION_OPCODE_IGMP, ofpacts); > > + encode_controller_op(ACTION_OPCODE_IGMP, ep->ctrl_meter_id, ofpacts); > > } > > > > static void > > @@ -1943,6 +1943,7 @@ format_PUT_ND(const struct ovnact_put_mac_bind *put_mac, struct ds *s) > > > > static void > > encode_put_mac(const struct ovnact_put_mac_bind *put_mac, > > + const struct ovnact_encode_params *ep, > > enum mf_field_id ip_field, enum action_opcode opcode, > > struct ofpbuf *ofpacts) > > { > > @@ -1952,24 +1953,24 @@ encode_put_mac(const struct ovnact_put_mac_bind *put_mac, > > { expr_resolve_field(&put_mac->mac), MFF_ETH_SRC } > > }; > > encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > > - encode_controller_op(opcode, ofpacts); > > + encode_controller_op(opcode, ep->ctrl_meter_id, ofpacts); > > encode_restore_args(args, ARRAY_SIZE(args), ofpacts); > > } > > > > static void > > encode_PUT_ARP(const struct ovnact_put_mac_bind *put_mac, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > - encode_put_mac(put_mac, MFF_REG0, ACTION_OPCODE_PUT_ARP, ofpacts); > > + encode_put_mac(put_mac, ep, MFF_REG0, ACTION_OPCODE_PUT_ARP, ofpacts); > > } > > > > static void > > encode_PUT_ND(const struct ovnact_put_mac_bind *put_mac, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > - encode_put_mac(put_mac, MFF_XXREG0, ACTION_OPCODE_PUT_ND, ofpacts); > > + encode_put_mac(put_mac, ep, MFF_XXREG0, ACTION_OPCODE_PUT_ND, ofpacts); > > } > > > > static void > > @@ -2670,13 +2671,13 @@ encode_put_dhcpv6_option(const struct ovnact_gen_option *o, > > > > static void > > encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts *pdo, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > struct mf_subfield dst = expr_resolve_field(&pdo->dst); > > > > size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_PUT_DHCP_OPTS, > > - true, NX_CTLR_NO_METER, > > + true, ep->ctrl_meter_id, > > ofpacts); > > nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); > > ovs_be32 ofs = htonl(dst.ofs); > > @@ -2723,13 +2724,13 @@ encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts *pdo, > > > > static void > > encode_PUT_DHCPV6_OPTS(const struct ovnact_put_opts *pdo, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > struct mf_subfield dst = expr_resolve_field(&pdo->dst); > > > > size_t oc_offset = encode_start_controller_op( > > - ACTION_OPCODE_PUT_DHCPV6_OPTS, true, NX_CTLR_NO_METER, ofpacts); > > + ACTION_OPCODE_PUT_DHCPV6_OPTS, true, ep->ctrl_meter_id, ofpacts); > > nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); > > ovs_be32 ofs = htonl(dst.ofs); > > ofpbuf_put(ofpacts, &ofs, sizeof ofs); > > @@ -2756,10 +2757,11 @@ format_DHCP6_REPLY(const struct ovnact_null *a OVS_UNUSED, struct ds *s) > > > > static void > > encode_DHCP6_REPLY(const struct ovnact_null *a OVS_UNUSED, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > - encode_controller_op(ACTION_OPCODE_DHCP6_SERVER, ofpacts); > > + encode_controller_op(ACTION_OPCODE_DHCP6_SERVER, ep->ctrl_meter_id, > > + ofpacts); > > } > > > > static void > > @@ -2770,10 +2772,11 @@ format_BFD_MSG(const struct ovnact_null *a OVS_UNUSED, struct ds *s) > > > > static void > > encode_BFD_MSG(const struct ovnact_null *a OVS_UNUSED, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > - encode_controller_op(ACTION_OPCODE_BFD_MSG, ofpacts); > > + encode_controller_op(ACTION_OPCODE_BFD_MSG, ep->ctrl_meter_id, > > + ofpacts); > > } > > > > static void > > @@ -2868,13 +2871,13 @@ format_DNS_LOOKUP(const struct ovnact_result *dl, struct ds *s) > > > > static void > > encode_DNS_LOOKUP(const struct ovnact_result *dl, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > struct mf_subfield dst = expr_resolve_field(&dl->dst); > > > > size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_DNS_LOOKUP, > > - true, NX_CTLR_NO_METER, > > + true, ep->ctrl_meter_id, > > ofpacts); > > nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); > > ovs_be32 ofs = htonl(dst.ofs); > > @@ -3052,13 +3055,13 @@ encode_put_nd_ra_option(const struct ovnact_gen_option *o, > > > > static void > > encode_PUT_ND_RA_OPTS(const struct ovnact_put_opts *po, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > struct mf_subfield dst = expr_resolve_field(&po->dst); > > > > size_t oc_offset = encode_start_controller_op( > > - ACTION_OPCODE_PUT_ND_RA_OPTS, true, NX_CTLR_NO_METER, ofpacts); > > + ACTION_OPCODE_PUT_ND_RA_OPTS, true, ep->ctrl_meter_id, ofpacts); > > nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); > > ovs_be32 ofs = htonl(dst.ofs); > > ofpbuf_put(ofpacts, &ofs, sizeof ofs); > > @@ -3341,7 +3344,7 @@ format_OVNFIELD_LOAD(const struct ovnact_load *load , struct ds *s) > > > > static void > > encode_OVNFIELD_LOAD(const struct ovnact_load *load, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > const struct ovn_field *f = ovn_field_from_name(load->dst.symbol->name); > > @@ -3349,7 +3352,7 @@ encode_OVNFIELD_LOAD(const struct ovnact_load *load, > > case OVN_ICMP4_FRAG_MTU: { > > size_t oc_offset = encode_start_controller_op( > > ACTION_OPCODE_PUT_ICMP4_FRAG_MTU, true, > > - NX_CTLR_NO_METER, ofpacts); > > + ep->ctrl_meter_id, ofpacts); > > ofpbuf_put(ofpacts, &load->imm.value.be16_int, sizeof(ovs_be16)); > > encode_finish_controller_op(oc_offset, ofpacts); > > break; > > @@ -3357,7 +3360,7 @@ encode_OVNFIELD_LOAD(const struct ovnact_load *load, > > case OVN_ICMP6_FRAG_MTU: { > > size_t oc_offset = encode_start_controller_op( > > ACTION_OPCODE_PUT_ICMP6_FRAG_MTU, true, > > - NX_CTLR_NO_METER, ofpacts); > > + ep->ctrl_meter_id, ofpacts); > > ofpbuf_put(ofpacts, &load->imm.value.be32_int, sizeof(ovs_be32)); > > encode_finish_controller_op(oc_offset, ofpacts); > > break; > > @@ -3461,7 +3464,7 @@ encode_BIND_VPORT(const struct ovnact_bind_vport *vp, > > }; > > encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > > size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_BIND_VPORT, > > - false, NX_CTLR_NO_METER, > > + false, ep->ctrl_meter_id, > > ofpacts); > > ovs_be32 vp_key = htonl(vport_key); > > ofpbuf_put(ofpacts, &vp_key, sizeof(ovs_be32)); > > @@ -3499,14 +3502,15 @@ format_HANDLE_SVC_CHECK(const struct ovnact_handle_svc_check *svc_chk, > > > > static void > > encode_HANDLE_SVC_CHECK(const struct ovnact_handle_svc_check *svc_chk, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > const struct arg args[] = { > > { expr_resolve_field(&svc_chk->port), MFF_LOG_INPORT }, > > }; > > encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > > - encode_controller_op(ACTION_OPCODE_HANDLE_SVC_CHECK, ofpacts); > > + encode_controller_op(ACTION_OPCODE_HANDLE_SVC_CHECK, ep->ctrl_meter_id, > > + ofpacts); > > encode_restore_args(args, ARRAY_SIZE(args), ofpacts); > > } > > > > @@ -3755,7 +3759,7 @@ format_PUT_FDB(const struct ovnact_put_fdb *put_fdb, struct ds *s) > > > > static void > > encode_PUT_FDB(const struct ovnact_put_fdb *put_fdb, > > - const struct ovnact_encode_params *ep OVS_UNUSED, > > + const struct ovnact_encode_params *ep, > > struct ofpbuf *ofpacts) > > { > > const struct arg args[] = { > > @@ -3763,7 +3767,7 @@ encode_PUT_FDB(const struct ovnact_put_fdb *put_fdb, > > { expr_resolve_field(&put_fdb->mac), MFF_ETH_SRC } > > }; > > encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > > - encode_controller_op(ACTION_OPCODE_PUT_FDB, ofpacts); > > + encode_controller_op(ACTION_OPCODE_PUT_FDB, ep->ctrl_meter_id, ofpacts); > > encode_restore_args(args, ARRAY_SIZE(args), ofpacts); > > } > > > > diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema > > index 205a30a37..609699475 100644 > > --- a/ovn-sb.ovsschema > > +++ b/ovn-sb.ovsschema > > @@ -1,7 +1,7 @@ > > { > > "name": "OVN_Southbound", > > - "version": "20.17.0", > > - "cksum": "669123379 26536", > > + "version": "20.18.0", > > + "cksum": "3870294693 26668", > > "tables": { > > "SB_Global": { > > "columns": { > > @@ -109,6 +109,8 @@ > > "maxInteger": 65535}}}, > > "match": {"type": "string"}, > > "actions": {"type": "string"}, > > + "controller_meter": {"type": {"key": {"type": "string"}, > > + "min": 0, "max": 1}}, > > "external_ids": { > > "type": {"key": "string", "value": "string", > > "min": 0, "max": "unlimited"}}}, > > diff --git a/ovn-sb.xml b/ovn-sb.xml > > index 258a12b4e..57c522db3 100644 > > --- a/ovn-sb.xml > > +++ b/ovn-sb.xml > > @@ -2441,6 +2441,12 @@ tcp.flags = RST; > > </dl> > > </column> > > > > + <column name="controller_meter"> > > + The name of the meter in table <ref table="Meter"/> to be used for > > + all packets that the logical flow might send to > > + <code>ovn-controller</code>. > > + </column> > > + > > <column name="external_ids" key="stage-name"> > > Human-readable name for this flow's stage in the pipeline. > > </column> > > >
diff --git a/controller/lflow.c b/controller/lflow.c index 680b8cca1..684fc43e6 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -557,6 +557,26 @@ update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t n_conjs) return false; } +static void +lflow_parse_ctrl_meter(const struct sbrec_logical_flow *lflow, + struct ovn_extend_table *meter_table, + uint32_t *meter_id) +{ + *meter_id = NX_CTLR_NO_METER; + + if (lflow->controller_meter) { + *meter_id = ovn_extend_table_assign_id(meter_table, + lflow->controller_meter, + lflow->header_.uuid); + if (*meter_id == EXT_TABLE_ID_INVALID) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Unable to assign id for meter: %s", + lflow->controller_meter); + return; + } + } +} + static void add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, const struct sbrec_datapath_binding *dp, @@ -572,6 +592,13 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, .dp = dp, }; + /* Parse any meter to be used if this flow should punt packets to + * controller. + */ + uint32_t ctrl_meter_id = NX_CTLR_NO_METER; + lflow_parse_ctrl_meter(lflow, l_ctx_out->meter_table, + &ctrl_meter_id); + /* Encode OVN logical actions into OpenFlow. */ uint64_t ofpacts_stub[1024 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); @@ -595,6 +622,7 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, .ct_snat_vip_ptable = OFTABLE_CT_SNAT_FOR_VIP, .fdb_ptable = OFTABLE_GET_FDB, .fdb_lookup_ptable = OFTABLE_LOOKUP_FDB, + .ctrl_meter_id = ctrl_meter_id, }; ovnacts_encode(ovnacts->data, ovnacts->size, &ep, &ofpacts); @@ -621,9 +649,10 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, } } if (!m->n) { - ofctrl_add_flow(l_ctx_out->flow_table, ptable, lflow->priority, - lflow->header_.uuid.parts[0], &m->match, &ofpacts, - &lflow->header_.uuid); + ofctrl_add_flow_meter(l_ctx_out->flow_table, ptable, lflow->priority, + lflow->header_.uuid.parts[0], &m->match, + &ofpacts, &lflow->header_.uuid, + ctrl_meter_id); } else { uint64_t conj_stubs[64 / 8]; struct ofpbuf conj; @@ -641,7 +670,8 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow, ofctrl_add_or_append_flow(l_ctx_out->flow_table, ptable, lflow->priority, 0, - &m->match, &conj, &lflow->header_.uuid); + &m->match, &conj, &lflow->header_.uuid, + ctrl_meter_id); ofpbuf_uninit(&conj); } } diff --git a/controller/ofctrl.c b/controller/ofctrl.c index c29c3d180..126df7741 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -66,6 +66,7 @@ struct ovn_flow { struct ofpact *ofpacts; size_t ofpacts_len; uint64_t cookie; + uint32_t ctrl_meter_id; /* Meter to be used for controller actions. */ }; /* A desired flow, in struct ovn_desired_flow_table, calculated by the @@ -220,7 +221,8 @@ static struct desired_flow *desired_flow_alloc( uint16_t priority, uint64_t cookie, const struct match *match, - const struct ofpbuf *actions); + const struct ofpbuf *actions, + uint32_t meter_id); static struct desired_flow *desired_flow_lookup( struct ovn_desired_flow_table *, const struct ovn_flow *target); @@ -1025,10 +1027,10 @@ ofctrl_check_and_add_flow(struct ovn_desired_flow_table *flow_table, uint64_t cookie, const struct match *match, const struct ofpbuf *actions, const struct uuid *sb_uuid, - bool log_duplicate_flow) + uint32_t meter_id, bool log_duplicate_flow) { struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie, - match, actions); + match, actions, meter_id); if (desired_flow_lookup_check_uuid(flow_table, &f->flow, sb_uuid)) { if (log_duplicate_flow) { @@ -1055,9 +1057,19 @@ ofctrl_add_flow(struct ovn_desired_flow_table *desired_flows, uint8_t table_id, uint16_t priority, uint64_t cookie, const struct match *match, const struct ofpbuf *actions, const struct uuid *sb_uuid) +{ + ofctrl_add_flow_meter(desired_flows, table_id, priority, cookie, + match, actions, sb_uuid, NX_CTLR_NO_METER); +} + +void +ofctrl_add_flow_meter(struct ovn_desired_flow_table *desired_flows, + uint8_t table_id, uint16_t priority, uint64_t cookie, + const struct match *match, const struct ofpbuf *actions, + const struct uuid *sb_uuid, uint32_t meter_id) { ofctrl_check_and_add_flow(desired_flows, table_id, priority, cookie, - match, actions, sb_uuid, true); + match, actions, sb_uuid, meter_id, true); } /* Either add a new flow, or append actions on an existing flow. If the @@ -1068,12 +1080,14 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, uint8_t table_id, uint16_t priority, uint64_t cookie, const struct match *match, const struct ofpbuf *actions, - const struct uuid *sb_uuid) + const struct uuid *sb_uuid, + uint32_t meter_id) { struct desired_flow *existing; struct desired_flow *f; - f = desired_flow_alloc(table_id, priority, cookie, match, actions); + f = desired_flow_alloc(table_id, priority, cookie, match, actions, + meter_id); existing = desired_flow_lookup_conjunctive(desired_flows, &f->flow); if (existing) { /* There's already a flow with this particular match and action @@ -1278,7 +1292,7 @@ ofctrl_flood_remove_flows(struct ovn_desired_flow_table *flow_table, static void ovn_flow_init(struct ovn_flow *f, uint8_t table_id, uint16_t priority, uint64_t cookie, const struct match *match, - const struct ofpbuf *actions) + const struct ofpbuf *actions, uint32_t meter_id) { f->table_id = table_id; f->priority = priority; @@ -1287,11 +1301,13 @@ ovn_flow_init(struct ovn_flow *f, uint8_t table_id, uint16_t priority, f->ofpacts_len = actions->size; f->hash = ovn_flow_match_hash(f); f->cookie = cookie; + f->ctrl_meter_id = meter_id; } static struct desired_flow * desired_flow_alloc(uint8_t table_id, uint16_t priority, uint64_t cookie, - const struct match *match, const struct ofpbuf *actions) + const struct match *match, const struct ofpbuf *actions, + uint32_t meter_id) { struct desired_flow *f = xmalloc(sizeof *f); ovs_list_init(&f->references); @@ -1300,7 +1316,7 @@ desired_flow_alloc(uint8_t table_id, uint16_t priority, uint64_t cookie, ovs_list_init(&f->track_list_node); f->installed_flow = NULL; f->is_deleted = false; - ovn_flow_init(&f->flow, table_id, priority, cookie, match, actions); + ovn_flow_init(&f->flow, table_id, priority, cookie, match, actions, meter_id); return f; } @@ -1326,6 +1342,7 @@ installed_flow_dup(struct desired_flow *src) dst->flow.ofpacts_len = src->flow.ofpacts_len; dst->flow.hash = src->flow.hash; dst->flow.cookie = src->flow.cookie; + dst->flow.ctrl_meter_id = src->flow.ctrl_meter_id; return dst; } @@ -1352,6 +1369,7 @@ desired_flow_lookup__(struct ovn_desired_flow_table *flow_table, struct ovn_flow *f = &d->flow; if (f->table_id == target->table_id && f->priority == target->priority + && f->ctrl_meter_id == target->ctrl_meter_id && minimatch_equal(&f->match, &target->match)) { if (!match_cb || match_cb(d, arg)) { diff --git a/controller/ofctrl.h b/controller/ofctrl.h index 88769566a..db374d4e8 100644 --- a/controller/ofctrl.h +++ b/controller/ofctrl.h @@ -78,7 +78,15 @@ void ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows, uint8_t table_id, uint16_t priority, uint64_t cookie, const struct match *match, const struct ofpbuf *actions, - const struct uuid *sb_uuid); + const struct uuid *sb_uuid, + uint32_t meter_id); + +void ofctrl_add_flow_meter(struct ovn_desired_flow_table *desired_flows, + uint8_t table_id, uint16_t priority, + uint64_t cookie, const struct match *match, + const struct ofpbuf *actions, + const struct uuid *sb_uuid, + uint32_t meter_id); /* Removes a bundles of flows from the flow table for a specific sb_uuid. The * flows are removed only if they are not referenced by any other sb_uuid(s). @@ -112,7 +120,8 @@ void ofctrl_check_and_add_flow(struct ovn_desired_flow_table *, uint8_t table_id, uint16_t priority, uint64_t cookie, const struct match *, const struct ofpbuf *ofpacts, - const struct uuid *, bool log_duplicate_flow); + const struct uuid *, uint32_t meter_id, + bool log_duplicate_flow); bool ofctrl_is_connected(void); diff --git a/controller/physical.c b/controller/physical.c index 96c959d18..95f92a85e 100644 --- a/controller/physical.c +++ b/controller/physical.c @@ -858,7 +858,8 @@ put_local_common_flows(uint32_t dp_key, uint32_t port_key, put_resubmit(OFTABLE_LOG_TO_PHY, ofpacts_p); put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p)); ofctrl_check_and_add_flow(flow_table, OFTABLE_SAVE_INPORT, 100, 0, - &match, ofpacts_p, hc_uuid, false); + &match, ofpacts_p, hc_uuid, NX_CTLR_NO_METER, + false); } } diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 040213177..ab03df12c 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -795,6 +795,8 @@ struct ovnact_encode_params { * 'get_fdb' to resubmit. */ uint8_t fdb_lookup_ptable; /* OpenFlow table for * 'lookup_fdb' to resubmit. */ + uint32_t ctrl_meter_id; /* Meter to be used if the resulting flow + sends packets to controller. */ }; void ovnacts_encode(const struct ovnact[], size_t ovnacts_len, diff --git a/lib/actions.c b/lib/actions.c index b3433f49e..155b4a45a 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -105,10 +105,10 @@ encode_finish_controller_op(size_t ofs, struct ofpbuf *ofpacts) } static void -encode_controller_op(enum action_opcode opcode, struct ofpbuf *ofpacts) +encode_controller_op(enum action_opcode opcode, uint32_t meter_id, + struct ofpbuf *ofpacts) { - size_t ofs = encode_start_controller_op(opcode, false, NX_CTLR_NO_METER, - ofpacts); + size_t ofs = encode_start_controller_op(opcode, false, meter_id, ofpacts); encode_finish_controller_op(ofs, ofpacts); } @@ -1647,7 +1647,7 @@ encode_nested_actions(const struct ovnact_nest *on, * packet to ARP or NA and then send the packet and actions back to the * switch inside an OFPT_PACKET_OUT message. */ size_t oc_offset = encode_start_controller_op(opcode, false, - NX_CTLR_NO_METER, ofpacts); + ep->ctrl_meter_id, ofpacts); ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size, ofpacts, OFP15_VERSION); encode_finish_controller_op(oc_offset, ofpacts); @@ -1698,10 +1698,10 @@ encode_ICMP6_ERROR(const struct ovnact_nest *on, static void encode_IGMP(const struct ovnact_null *a OVS_UNUSED, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { - encode_controller_op(ACTION_OPCODE_IGMP, ofpacts); + encode_controller_op(ACTION_OPCODE_IGMP, ep->ctrl_meter_id, ofpacts); } static void @@ -1943,6 +1943,7 @@ format_PUT_ND(const struct ovnact_put_mac_bind *put_mac, struct ds *s) static void encode_put_mac(const struct ovnact_put_mac_bind *put_mac, + const struct ovnact_encode_params *ep, enum mf_field_id ip_field, enum action_opcode opcode, struct ofpbuf *ofpacts) { @@ -1952,24 +1953,24 @@ encode_put_mac(const struct ovnact_put_mac_bind *put_mac, { expr_resolve_field(&put_mac->mac), MFF_ETH_SRC } }; encode_setup_args(args, ARRAY_SIZE(args), ofpacts); - encode_controller_op(opcode, ofpacts); + encode_controller_op(opcode, ep->ctrl_meter_id, ofpacts); encode_restore_args(args, ARRAY_SIZE(args), ofpacts); } static void encode_PUT_ARP(const struct ovnact_put_mac_bind *put_mac, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { - encode_put_mac(put_mac, MFF_REG0, ACTION_OPCODE_PUT_ARP, ofpacts); + encode_put_mac(put_mac, ep, MFF_REG0, ACTION_OPCODE_PUT_ARP, ofpacts); } static void encode_PUT_ND(const struct ovnact_put_mac_bind *put_mac, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { - encode_put_mac(put_mac, MFF_XXREG0, ACTION_OPCODE_PUT_ND, ofpacts); + encode_put_mac(put_mac, ep, MFF_XXREG0, ACTION_OPCODE_PUT_ND, ofpacts); } static void @@ -2670,13 +2671,13 @@ encode_put_dhcpv6_option(const struct ovnact_gen_option *o, static void encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts *pdo, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { struct mf_subfield dst = expr_resolve_field(&pdo->dst); size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_PUT_DHCP_OPTS, - true, NX_CTLR_NO_METER, + true, ep->ctrl_meter_id, ofpacts); nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); ovs_be32 ofs = htonl(dst.ofs); @@ -2723,13 +2724,13 @@ encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts *pdo, static void encode_PUT_DHCPV6_OPTS(const struct ovnact_put_opts *pdo, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { struct mf_subfield dst = expr_resolve_field(&pdo->dst); size_t oc_offset = encode_start_controller_op( - ACTION_OPCODE_PUT_DHCPV6_OPTS, true, NX_CTLR_NO_METER, ofpacts); + ACTION_OPCODE_PUT_DHCPV6_OPTS, true, ep->ctrl_meter_id, ofpacts); nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); ovs_be32 ofs = htonl(dst.ofs); ofpbuf_put(ofpacts, &ofs, sizeof ofs); @@ -2756,10 +2757,11 @@ format_DHCP6_REPLY(const struct ovnact_null *a OVS_UNUSED, struct ds *s) static void encode_DHCP6_REPLY(const struct ovnact_null *a OVS_UNUSED, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { - encode_controller_op(ACTION_OPCODE_DHCP6_SERVER, ofpacts); + encode_controller_op(ACTION_OPCODE_DHCP6_SERVER, ep->ctrl_meter_id, + ofpacts); } static void @@ -2770,10 +2772,11 @@ format_BFD_MSG(const struct ovnact_null *a OVS_UNUSED, struct ds *s) static void encode_BFD_MSG(const struct ovnact_null *a OVS_UNUSED, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { - encode_controller_op(ACTION_OPCODE_BFD_MSG, ofpacts); + encode_controller_op(ACTION_OPCODE_BFD_MSG, ep->ctrl_meter_id, + ofpacts); } static void @@ -2868,13 +2871,13 @@ format_DNS_LOOKUP(const struct ovnact_result *dl, struct ds *s) static void encode_DNS_LOOKUP(const struct ovnact_result *dl, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { struct mf_subfield dst = expr_resolve_field(&dl->dst); size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_DNS_LOOKUP, - true, NX_CTLR_NO_METER, + true, ep->ctrl_meter_id, ofpacts); nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); ovs_be32 ofs = htonl(dst.ofs); @@ -3052,13 +3055,13 @@ encode_put_nd_ra_option(const struct ovnact_gen_option *o, static void encode_PUT_ND_RA_OPTS(const struct ovnact_put_opts *po, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { struct mf_subfield dst = expr_resolve_field(&po->dst); size_t oc_offset = encode_start_controller_op( - ACTION_OPCODE_PUT_ND_RA_OPTS, true, NX_CTLR_NO_METER, ofpacts); + ACTION_OPCODE_PUT_ND_RA_OPTS, true, ep->ctrl_meter_id, ofpacts); nx_put_header(ofpacts, dst.field->id, OFP15_VERSION, false); ovs_be32 ofs = htonl(dst.ofs); ofpbuf_put(ofpacts, &ofs, sizeof ofs); @@ -3341,7 +3344,7 @@ format_OVNFIELD_LOAD(const struct ovnact_load *load , struct ds *s) static void encode_OVNFIELD_LOAD(const struct ovnact_load *load, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { const struct ovn_field *f = ovn_field_from_name(load->dst.symbol->name); @@ -3349,7 +3352,7 @@ encode_OVNFIELD_LOAD(const struct ovnact_load *load, case OVN_ICMP4_FRAG_MTU: { size_t oc_offset = encode_start_controller_op( ACTION_OPCODE_PUT_ICMP4_FRAG_MTU, true, - NX_CTLR_NO_METER, ofpacts); + ep->ctrl_meter_id, ofpacts); ofpbuf_put(ofpacts, &load->imm.value.be16_int, sizeof(ovs_be16)); encode_finish_controller_op(oc_offset, ofpacts); break; @@ -3357,7 +3360,7 @@ encode_OVNFIELD_LOAD(const struct ovnact_load *load, case OVN_ICMP6_FRAG_MTU: { size_t oc_offset = encode_start_controller_op( ACTION_OPCODE_PUT_ICMP6_FRAG_MTU, true, - NX_CTLR_NO_METER, ofpacts); + ep->ctrl_meter_id, ofpacts); ofpbuf_put(ofpacts, &load->imm.value.be32_int, sizeof(ovs_be32)); encode_finish_controller_op(oc_offset, ofpacts); break; @@ -3461,7 +3464,7 @@ encode_BIND_VPORT(const struct ovnact_bind_vport *vp, }; encode_setup_args(args, ARRAY_SIZE(args), ofpacts); size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_BIND_VPORT, - false, NX_CTLR_NO_METER, + false, ep->ctrl_meter_id, ofpacts); ovs_be32 vp_key = htonl(vport_key); ofpbuf_put(ofpacts, &vp_key, sizeof(ovs_be32)); @@ -3499,14 +3502,15 @@ format_HANDLE_SVC_CHECK(const struct ovnact_handle_svc_check *svc_chk, static void encode_HANDLE_SVC_CHECK(const struct ovnact_handle_svc_check *svc_chk, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { const struct arg args[] = { { expr_resolve_field(&svc_chk->port), MFF_LOG_INPORT }, }; encode_setup_args(args, ARRAY_SIZE(args), ofpacts); - encode_controller_op(ACTION_OPCODE_HANDLE_SVC_CHECK, ofpacts); + encode_controller_op(ACTION_OPCODE_HANDLE_SVC_CHECK, ep->ctrl_meter_id, + ofpacts); encode_restore_args(args, ARRAY_SIZE(args), ofpacts); } @@ -3755,7 +3759,7 @@ format_PUT_FDB(const struct ovnact_put_fdb *put_fdb, struct ds *s) static void encode_PUT_FDB(const struct ovnact_put_fdb *put_fdb, - const struct ovnact_encode_params *ep OVS_UNUSED, + const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { const struct arg args[] = { @@ -3763,7 +3767,7 @@ encode_PUT_FDB(const struct ovnact_put_fdb *put_fdb, { expr_resolve_field(&put_fdb->mac), MFF_ETH_SRC } }; encode_setup_args(args, ARRAY_SIZE(args), ofpacts); - encode_controller_op(ACTION_OPCODE_PUT_FDB, ofpacts); + encode_controller_op(ACTION_OPCODE_PUT_FDB, ep->ctrl_meter_id, ofpacts); encode_restore_args(args, ARRAY_SIZE(args), ofpacts); } diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index 205a30a37..609699475 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "20.17.0", - "cksum": "669123379 26536", + "version": "20.18.0", + "cksum": "3870294693 26668", "tables": { "SB_Global": { "columns": { @@ -109,6 +109,8 @@ "maxInteger": 65535}}}, "match": {"type": "string"}, "actions": {"type": "string"}, + "controller_meter": {"type": {"key": {"type": "string"}, + "min": 0, "max": 1}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, diff --git a/ovn-sb.xml b/ovn-sb.xml index 258a12b4e..57c522db3 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -2441,6 +2441,12 @@ tcp.flags = RST; </dl> </column> + <column name="controller_meter"> + The name of the meter in table <ref table="Meter"/> to be used for + all packets that the logical flow might send to + <code>ovn-controller</code>. + </column> + <column name="external_ids" key="stage-name"> Human-readable name for this flow's stage in the pipeline. </column>