[ovs-dev] [RFC 2/3] OVN: introduce send_event() action
Numan Siddique
nusiddiq at redhat.com
Tue May 21 07:40:13 UTC 2019
On Thu, May 16, 2019 at 9:45 PM Lorenzo Bianconi <
lorenzo.bianconi at redhat.com> wrote:
> Add send_event() ovn action in order to allow ovs-vswitchd to report
> CMS related events.
> This commit introduces a new event, empty_lb_backends. This event is
> raised if a received packet is destined for a load balancer VIP that has
> no configured backend destinations. For this event, the event info
> includes the load balancer VIP, the load balancer UUID, and the
> transport protocol.
> The use case for this particular event is for the CMS to supply backend
> resources to handle this traffic. For example, in Openshift, this event
> can be used to spin up new containers to handle the incoming traffic.
>
> Signed-off-by: Mark Michelson <mmichels at redhat.com>
> Co-authored-by: Mark Michelson <mmichels at redhat.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
>
Hi Lorenzo,
Overall this series looks good to me. I haven't done any code review yet.
I have few initial comments.
How about renaming the action - "send_event" to "trigger_event" ? Just a
suggestion.
The action send_event takes the event_type as an integer. I would suggest
to take a string value instead.
something like - send_event(event = "lb_no_backends", vip = "10.0.0.1:80
<http://10.0.0.1/>", protocol...)
Thanks
Numan
---
> include/ovn/actions.h | 17 +++-
> ovn/controller/lflow.c | 8 ++
> ovn/controller/pinctrl.c | 109 ++++++++++++++++++++++++
> ovn/lib/actions.c | 169 ++++++++++++++++++++++++++++++++++++++
> ovn/lib/ovn-l7.h | 46 +++++++++++
> ovn/utilities/ovn-trace.c | 3 +
> tests/ovn.at | 10 +++
> tests/test-ovn.c | 11 ++-
> 8 files changed, 370 insertions(+), 3 deletions(-)
>
> diff --git a/include/ovn/actions.h b/include/ovn/actions.h
> index e07ad9aa3..0d5920023 100644
> --- a/include/ovn/actions.h
> +++ b/include/ovn/actions.h
> @@ -83,7 +83,8 @@ struct ovn_extend_table;
> OVNACT(ND_NS, ovnact_nest) \
> OVNACT(SET_METER, ovnact_set_meter) \
> OVNACT(OVNFIELD_LOAD, ovnact_load) \
> - OVNACT(CHECK_PKT_LARGER, ovnact_check_pkt_larger)
> + OVNACT(CHECK_PKT_LARGER, ovnact_check_pkt_larger) \
> + OVNACT(SEND_EVENT, ovnact_controller_event)
>
> /* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */
> enum OVS_PACKED_ENUM ovnact_type {
> @@ -318,6 +319,14 @@ struct ovnact_check_pkt_larger {
> struct expr_field dst; /* 1-bit destination field. */
> };
>
> +/* OVNACT_EVENT. */
> +struct ovnact_controller_event {
> + struct ovnact ovnact;
> + int event_type; /* controller event type */
> + struct ovnact_gen_option *options;
> + size_t n_options;
> +};
> +
> /* Internal use by the helpers below. */
> void ovnact_init(struct ovnact *, enum ovnact_type, size_t len);
> void *ovnact_put(struct ofpbuf *, enum ovnact_type, size_t len);
> @@ -486,6 +495,9 @@ enum action_opcode {
> * The actions, in OpenFlow 1.3 format, follow the action_header.
> */
> ACTION_OPCODE_ICMP4_ERROR,
> +
> + /* "send_event (event_type)" */
> + ACTION_OPCODE_EVENT,
> };
>
> /* Header. */
> @@ -515,6 +527,9 @@ struct ovnact_parse_params {
> /* hmap of 'struct gen_opts_map' to support 'put_nd_ra_opts' action */
> const struct hmap *nd_ra_opts;
>
> + /* Array of hmap of 'struct gen_opts_map' to support 'send_event'
> action */
> + const struct controller_event_options *controller_event_opts;
> +
> /* Each OVN flow exists in a logical table within a logical pipeline.
> * These parameters express this context for a set of OVN actions
> being
> * parsed:
> diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
> index 661407bcc..8d7f51204 100644
> --- a/ovn/controller/lflow.c
> +++ b/ovn/controller/lflow.c
> @@ -70,6 +70,7 @@ static void consider_logical_flow(
> struct hmap *dhcp_opts,
> struct hmap *dhcpv6_opts,
> struct hmap *nd_ra_opts,
> + struct controller_event_options *controller_event_opts,
> const struct shash *addr_sets,
> const struct shash *port_groups,
> const struct sset *active_tunnels,
> @@ -173,11 +174,15 @@ add_logical_flows(
> struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts);
> nd_ra_opts_init(&nd_ra_opts);
>
> + struct controller_event_options controller_event_opts;
> + controller_event_opts_init(&controller_event_opts);
> +
> SBREC_LOGICAL_FLOW_TABLE_FOR_EACH (lflow, logical_flow_table) {
> consider_logical_flow(sbrec_multicast_group_by_name_datapath,
> sbrec_port_binding_by_name,
> lflow, local_datapaths,
> chassis, &dhcp_opts, &dhcpv6_opts,
> &nd_ra_opts,
> + &controller_event_opts,
> addr_sets, port_groups, active_tunnels,
> local_lport_ids, &conj_id_ofs,
> flow_table, group_table, meter_table);
> @@ -186,6 +191,7 @@ add_logical_flows(
> dhcp_opts_destroy(&dhcp_opts);
> dhcp_opts_destroy(&dhcpv6_opts);
> nd_ra_opts_destroy(&nd_ra_opts);
> + controller_event_opts_destroy(&controller_event_opts);
> }
>
> static void
> @@ -198,6 +204,7 @@ consider_logical_flow(
> struct hmap *dhcp_opts,
> struct hmap *dhcpv6_opts,
> struct hmap *nd_ra_opts,
> + struct controller_event_options *controller_event_opts,
> const struct shash *addr_sets,
> const struct shash *port_groups,
> const struct sset *active_tunnels,
> @@ -237,6 +244,7 @@ consider_logical_flow(
> .dhcp_opts = dhcp_opts,
> .dhcpv6_opts = dhcpv6_opts,
> .nd_ra_opts = nd_ra_opts,
> + .controller_event_opts = controller_event_opts,
>
> .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS,
> .n_tables = LOG_PIPELINE_LEN,
> diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c
> index ca191d961..6cc98c617 100644
> --- a/ovn/controller/pinctrl.c
> +++ b/ovn/controller/pinctrl.c
> @@ -208,6 +208,10 @@ static void pinctrl_handle_put_icmp4_frag_mtu(struct
> rconn *swconn,
> struct ofputil_packet_in
> *pin,
> struct ofpbuf *userdata,
> struct ofpbuf
> *continuation);
> +static void
> +pinctrl_handle_event(struct ofpbuf *userdata)
> + OVS_REQUIRES(pinctrl_mutex);
> +static void wait_controller_event(struct ovsdb_idl_txn *ovnsb_idl_txn);
> static void init_ipv6_ras(void);
> static void destroy_ipv6_ras(void);
> static void ipv6_ra_wait(long long int send_ipv6_ra_time);
> @@ -1870,6 +1874,12 @@ process_packet_in(struct rconn *swconn, const
> struct ofp_header *msg)
> &pin, &userdata, &continuation);
> break;
>
> + case ACTION_OPCODE_EVENT:
> + ovs_mutex_lock(&pinctrl_mutex);
> + pinctrl_handle_event(&userdata);
> + ovs_mutex_unlock(&pinctrl_mutex);
> + break;
> +
> default:
> VLOG_WARN_RL(&rl, "unrecognized packet-in opcode %"PRIu32,
> ntohl(ah->opcode));
> @@ -2378,6 +2388,7 @@ void
> pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn)
> {
> wait_put_mac_bindings(ovnsb_idl_txn);
> + wait_controller_event(ovnsb_idl_txn);
> int64_t new_seq = seq_read(pinctrl_main_seq);
> seq_wait(pinctrl_main_seq, new_seq);
> }
> @@ -3417,3 +3428,101 @@ exit:
> dp_packet_delete(pkt_out);
> }
> }
> +
> +static void
> +wait_controller_event(struct ovsdb_idl_txn *ovnsb_idl_txn)
> +{
> + if (!ovnsb_idl_txn) {
> + return;
> + }
> +
> + for (size_t i = 0; i < OVN_EVENT_MAX; i++) {
> + if (!hmap_is_empty(&event_table[i])) {
> + poll_immediate_wake();
> + break;
> + }
> + }
> +}
> +
> +static bool
> +pinctrl_handle_empty_lb_backends_opts(struct ofpbuf *userdata)
> +{
> + struct controller_event_opt_header *userdata_opt;
> + uint32_t hash = 0;
> + char *vip = NULL;
> + char *protocol = NULL;
> + char *load_balancer = NULL;
> +
> + while (userdata->size) {
> + userdata_opt = ofpbuf_try_pull(userdata, sizeof *userdata_opt);
> + if (!userdata_opt) {
> + return false;
> + }
> + size_t size = ntohs(userdata_opt->size);
> + char *userdata_opt_data = ofpbuf_try_pull(userdata, size);
> + if (!userdata_opt_data) {
> + return false;
> + }
> + switch (ntohs(userdata_opt->opt_code)) {
> + case EMPTY_LB_VIP:
> + vip = xmemdup0(userdata_opt_data, size);
> + break;
> + case EMPTY_LB_PROTOCOL:
> + protocol = xmemdup0(userdata_opt_data, size);
> + break;
> + case EMPTY_LB_LOAD_BALANCER:
> + load_balancer = xmemdup0(userdata_opt_data, size);
> + break;
> + default:
> + OVS_NOT_REACHED();
> + }
> + hash = hash_bytes(userdata_opt_data, size, hash);
> + }
> + ovs_assert(vip && protocol && load_balancer);
> +
> + struct empty_lb_backends_event *event;
> +
> + event = pinctrl_find_empty_lb_backends_event(vip, protocol,
> + load_balancer, hash);
> + if (!event) {
> + if (hmap_count(&event_table[OVN_EVENT_EMPTY_LB_BACKENDS]) >=
> 1000) {
> + COVERAGE_INC(pinctrl_drop_controller_event);
> + return false;
> + }
> +
> + event = xzalloc(sizeof *event);
> + hmap_insert(&event_table[OVN_EVENT_EMPTY_LB_BACKENDS],
> + &event->hmap_node, hash);
> + event->vip = vip;
> + event->protocol = protocol;
> + event->load_balancer = load_balancer;
> + notify_pinctrl_main();
> + } else {
> + free(vip);
> + free(protocol);
> + free(load_balancer);
> + }
> + return true;
> +}
> +
> +static void
> +pinctrl_handle_event(struct ofpbuf *userdata)
> + OVS_REQUIRES(pinctrl_mutex)
> +{
> + ovs_be32 *pevent;
> +
> + pevent = ofpbuf_try_pull(userdata, sizeof *pevent);
> + if (!pevent) {
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> + VLOG_WARN_RL(&rl, "event not present in the userdata");
> + return;
> + }
> +
> + switch (ntohl(*pevent)) {
> + case OVN_EVENT_EMPTY_LB_BACKENDS:
> + pinctrl_handle_empty_lb_backends_opts(userdata);
> + break;
> + default:
> + return;
> + }
> +}
> diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
> index d5909911d..1603b5d57 100644
> --- a/ovn/lib/actions.c
> +++ b/ovn/lib/actions.c
> @@ -38,6 +38,8 @@
> #include "packets.h"
> #include "openvswitch/shash.h"
> #include "simap.h"
> +#include "uuid.h"
> +#include "socket-util.h"
>
> VLOG_DEFINE_THIS_MODULE(actions);
>
> @@ -1258,6 +1260,20 @@ format_CLONE(const struct ovnact_nest *nest, struct
> ds *s)
> format_nested_action(nest, "clone", s);
> }
>
> +static void
> +format_SEND_EVENT(const struct ovnact_controller_event *event,
> + struct ds *s)
> +{
> + ds_put_format(s, "send_event(event = %d", event->event_type);
> + for (const struct ovnact_gen_option *o = event->options;
> + o < &event->options[event->n_options]; o++) {
> + ds_put_cstr(s, ", ");
> + ds_put_format(s, "%s = ", o->option->name);
> + expr_constant_set_format(&o->value, s);
> + }
> + ds_put_cstr(s, ");");
> +}
> +
> static void
> encode_nested_actions(const struct ovnact_nest *on,
> const struct ovnact_encode_params *ep,
> @@ -1361,6 +1377,52 @@ encode_CLONE(const struct ovnact_nest *on,
> ofpact_finish_CLONE(ofpacts, &clone);
> }
>
> +static void
> +encode_event_empty_lb_backends_opts(struct ofpbuf *ofpacts,
> + const struct ovnact_controller_event *event)
> +{
> + for (const struct ovnact_gen_option *o = event->options;
> + o < &event->options[event->n_options]; o++) {
> + struct controller_event_opt_header *hdr =
> + ofpbuf_put_uninit(ofpacts, sizeof *hdr);
> + const union expr_constant *c = o->value.values;
> + size_t size;
> + hdr->opt_code = htons(o->option->code);
> + if (!strcmp(o->option->type, "str")) {
> + size = strlen(c->string);
> + hdr->size = htons(size);
> + ofpbuf_put(ofpacts, c->string, size);
> + } else {
> + /* All empty_lb_backends fields are of type 'str' */
> + OVS_NOT_REACHED();
> + }
> + }
> +}
> +
> +static void
> +encode_SEND_EVENT(const struct ovnact_controller_event *event,
> + const struct ovnact_encode_params *ep OVS_UNUSED,
> + struct ofpbuf *ofpacts)
> +{
> + size_t oc_offset;
> +
> + oc_offset = encode_start_controller_op(ACTION_OPCODE_EVENT, false,
> + NX_CTLR_NO_METER, ofpacts);
> + ovs_be32 ofs = htonl(event->event_type);
> + ofpbuf_put(ofpacts, &ofs, sizeof ofs);
> +
> + switch (event->event_type) {
> + case OVN_EVENT_EMPTY_LB_BACKENDS:
> + encode_event_empty_lb_backends_opts(ofpacts, event);
> + break;
> + case OVN_EVENT_MAX:
> + default:
> + OVS_NOT_REACHED();
> + }
> +
> + encode_finish_controller_op(oc_offset, ofpacts);
> +}
> +
> static void
> ovnact_nest_free(struct ovnact_nest *on)
> {
> @@ -1575,6 +1637,111 @@ free_gen_options(struct ovnact_gen_option
> *options, size_t n)
> free(options);
> }
>
> +static void
> +validate_empty_lb_backends(struct action_context *ctx,
> + const struct ovnact_gen_option *options,
> + size_t n_options)
> +{
> + for (const struct ovnact_gen_option *o = options;
> + o < &options[n_options]; o++) {
> + const union expr_constant *c = o->value.values;
> + struct sockaddr_storage ss;
> + struct uuid uuid;
> +
> + if (o->value.n_values > 1 || !c->string) {
> + lexer_error(ctx->lexer, "Invalid value for \"%s\" option",
> + o->option->name);
> + return;
> + }
> +
> + switch (o->option->code) {
> + case EMPTY_LB_VIP:
> + if (!inet_parse_active(c->string, 0, &ss, false)) {
> + lexer_error(ctx->lexer, "Invalid load balancer VIP '%s'",
> + c->string);
> + return;
> + }
> + break;
> + case EMPTY_LB_PROTOCOL:
> + if (strcmp(c->string, "tcp") && strcmp(c->string, "udp")) {
> + lexer_error(ctx->lexer,
> + "Load balancer protocol '%s' is not 'tcp' or 'udp'",
> + c->string);
> + return;
> + }
> + break;
> + case EMPTY_LB_LOAD_BALANCER:
> + if (!uuid_from_string(&uuid, c->string)) {
> + lexer_error(ctx->lexer, "Load balancer '%s' is not a
> UUID",
> + c->string);
> + return;
> + }
> + break;
> + }
> + }
> +}
> +
> +static void
> +parse_send_event(struct action_context *ctx,
> + struct ovnact_controller_event *event)
> +{
> + int event_type = 0;
> +
> + lexer_force_match(ctx->lexer, LEX_T_LPAREN);
> +
> + /* Event type must be listed first */
> + if (!lexer_match_id(ctx->lexer, "event")) {
> + lexer_syntax_error(ctx->lexer, "Expecting 'event' option");
> + return;
> + }
> + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
> + return;
> + }
> + if (!lexer_force_int(ctx->lexer, &event_type)) {
> + return;
> + }
> +
> + if (event_type < 0 || event_type >= OVN_EVENT_MAX) {
> + lexer_syntax_error(ctx->lexer, "Unknown event '%d'", event_type);
> + return;
> + }
> +
> + event->event_type = event_type;
> + lexer_match(ctx->lexer, LEX_T_COMMA);
> +
> + size_t allocated_options = 0;
> + while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
> + if (event->n_options >= allocated_options) {
> + event->options = x2nrealloc(event->options,
> &allocated_options,
> + sizeof *event->options);
> + }
> +
> + struct ovnact_gen_option *o = &event->options[event->n_options++];
> + memset(o, 0, sizeof *o);
> + parse_gen_opt(ctx, o,
> +
> &ctx->pp->controller_event_opts->event_opts[event_type],
> + event_to_string(event_type));
> + if (ctx->lexer->error) {
> + return;
> + }
> +
> + lexer_match(ctx->lexer, LEX_T_COMMA);
> + }
> +
> + switch (event_type) {
> + case OVN_EVENT_EMPTY_LB_BACKENDS:
> + validate_empty_lb_backends(ctx, event->options, event->n_options);
> + break;
> + default:
> + OVS_NOT_REACHED();
> + }
> +}
> +
> +static void
> +ovnact_controller_event_free(struct ovnact_controller_event *event
> OVS_UNUSED)
> +{
> +}
> +
> static void
> parse_put_opts(struct action_context *ctx, const struct expr_field *dst,
> struct ovnact_put_opts *po, const struct hmap *gen_opts,
> @@ -2511,6 +2678,8 @@ parse_action(struct action_context *ctx)
> parse_LOG(ctx);
> } else if (lexer_match_id(ctx->lexer, "set_meter")) {
> parse_set_meter_action(ctx);
> + } else if (lexer_match_id(ctx->lexer, "send_event")) {
> + parse_send_event(ctx, ovnact_put_SEND_EVENT(ctx->ovnacts));
> } else {
> lexer_syntax_error(ctx->lexer, "expecting action");
> }
> diff --git a/ovn/lib/ovn-l7.h b/ovn/lib/ovn-l7.h
> index c24201ef0..4ff458e90 100644
> --- a/ovn/lib/ovn-l7.h
> +++ b/ovn/lib/ovn-l7.h
> @@ -22,6 +22,7 @@
> #include <netinet/icmp6.h>
> #include "openvswitch/hmap.h"
> #include "hash.h"
> +#include "ovn/logical-fields.h"
>
> /* Generic options map which is used to store dhcpv4 opts and dhcpv6
> opts. */
> struct gen_opts_map {
> @@ -272,4 +273,49 @@ nd_ra_opts_init(struct hmap *nd_ra_opts)
> nd_ra_opt_add(nd_ra_opts, "mtu", ND_OPT_MTU, "uint32");
> }
>
> +#define EMPTY_LB_VIP 1
> +#define EMPTY_LB_PROTOCOL 2
> +#define EMPTY_LB_LOAD_BALANCER 3
> +
> +/* Used in the OpenFlow PACKET_IN userdata */
> +struct controller_event_opt_header {
> + ovs_be16 opt_code;
> + ovs_be16 size;
> +};
> +
> +struct controller_event_options {
> + struct hmap event_opts[OVN_EVENT_MAX];
> +};
> +
> +static inline void
> +controller_event_opt_add(struct controller_event_options *event_opts,
> + enum ovn_controller_event event_type, char
> *opt_name,
> + size_t opt_code, char *opt_type)
> +{
> + gen_opt_add(&event_opts->event_opts[event_type], opt_name, opt_code,
> + opt_type);
> +}
> +
> +static inline void
> +controller_event_opts_init(struct controller_event_options *opts)
> +{
> + for (size_t i = 0; i < OVN_EVENT_MAX; i++) {
> + hmap_init(&opts->event_opts[i]);
> + }
> + controller_event_opt_add(opts, OVN_EVENT_EMPTY_LB_BACKENDS, "vip",
> + EMPTY_LB_VIP, "str");
> + controller_event_opt_add(opts, OVN_EVENT_EMPTY_LB_BACKENDS,
> "protocol",
> + EMPTY_LB_PROTOCOL, "str");
> + controller_event_opt_add(opts, OVN_EVENT_EMPTY_LB_BACKENDS,
> + "load_balancer", EMPTY_LB_LOAD_BALANCER,
> "str");
> +}
> +
> +static inline void
> +controller_event_opts_destroy(struct controller_event_options *opts)
> +{
> + for (size_t i = 0; i < OVN_EVENT_MAX; i++) {
> + gen_opts_destroy(&opts->event_opts[i]);
> + }
> +}
> +
> #endif /* OVN_DHCP_H */
> diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c
> index 9718077aa..49c3511de 100644
> --- a/ovn/utilities/ovn-trace.c
> +++ b/ovn/utilities/ovn-trace.c
> @@ -2135,6 +2135,9 @@ trace_actions(const struct ovnact *ovnacts, size_t
> ovnacts_len,
> execute_ovnfield_load(ovnact_get_OVNFIELD_LOAD(a), super);
> break;
>
> + case OVNACT_SEND_EVENT:
> + break;
> +
> case OVNACT_CHECK_PKT_LARGER:
> break;
> }
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 6499df3d3..1c54dd920 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -1333,6 +1333,16 @@ tcp_reset { };
> encodes as controller(userdata=00.00.00.0b.00.00.00.00)
> has prereqs tcp
>
> +# send_event
> +send_event(event = 0, vip = "10.0.0.1:80", protocol = "tcp",
> load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
> + encodes as
> controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63)
> +
> +# Testing invalid vip results in extra error messages from socket-util.c
> +send_event(event = 0, vip = "10.0.0.1:80", protocol = "sctp",
> load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
> + Load balancer protocol 'sctp' is not 'tcp' or 'udp'
> +send_event(event = 0, vip = "10.0.0.1:80", protocol = "tcp",
> load_balancer = "bacon");
> + Load balancer 'bacon' is not a UUID
> +
> # Contradictionary prerequisites (allowed but not useful):
> ip4.src = ip6.src[0..31];
> encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]
> diff --git a/tests/test-ovn.c b/tests/test-ovn.c
> index 7cce9c2ae..619bd3f78 100644
> --- a/tests/test-ovn.c
> +++ b/tests/test-ovn.c
> @@ -157,7 +157,8 @@ create_symtab(struct shash *symtab)
>
> static void
> create_gen_opts(struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
> - struct hmap *nd_ra_opts)
> + struct hmap *nd_ra_opts,
> + struct controller_event_options *event_opts)
> {
> hmap_init(dhcp_opts);
> dhcp_opt_add(dhcp_opts, "offerip", 0, "ipv4");
> @@ -197,6 +198,9 @@ create_gen_opts(struct hmap *dhcp_opts, struct hmap
> *dhcpv6_opts,
> /* IPv6 ND RA options. */
> hmap_init(nd_ra_opts);
> nd_ra_opts_init(nd_ra_opts);
> +
> + /* OVN controller events options. */
> + controller_event_opts_init(event_opts);
> }
>
> static void
> @@ -1228,12 +1232,13 @@ test_parse_actions(struct ovs_cmdl_context *ctx
> OVS_UNUSED)
> struct hmap dhcp_opts;
> struct hmap dhcpv6_opts;
> struct hmap nd_ra_opts;
> + struct controller_event_options event_opts;
> struct simap ports;
> struct ds input;
> bool ok = true;
>
> create_symtab(&symtab);
> - create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts);
> + create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts, &event_opts);
>
> /* Initialize group ids. */
> struct ovn_extend_table group_table;
> @@ -1263,6 +1268,7 @@ test_parse_actions(struct ovs_cmdl_context *ctx
> OVS_UNUSED)
> .dhcp_opts = &dhcp_opts,
> .dhcpv6_opts = &dhcpv6_opts,
> .nd_ra_opts = &nd_ra_opts,
> + .controller_event_opts = &event_opts,
> .n_tables = 24,
> .cur_ltable = 10,
> };
> @@ -1350,6 +1356,7 @@ test_parse_actions(struct ovs_cmdl_context *ctx
> OVS_UNUSED)
> dhcp_opts_destroy(&dhcp_opts);
> dhcp_opts_destroy(&dhcpv6_opts);
> nd_ra_opts_destroy(&nd_ra_opts);
> + controller_event_opts_destroy(&event_opts);
> ovn_extend_table_destroy(&group_table);
> ovn_extend_table_destroy(&meter_table);
> exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
> --
> 2.20.1
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
More information about the dev
mailing list