On Tue, Aug 29, 2023 at 10:42 AM Ales Musil <amu...@redhat.com> wrote:

> If the flow size is bigger than UINT16_MAX it doesn't
> fit into openflow message. Programming of such flow will
> fail which results in disconnect of ofctrl. After reconnect
> we program everything from scratch, in case the long flow still
> remains the cycle continues. This causes the node to be almost
> unusable as there will be massive traffic disruptions.
>
> To prevent that check if the flow is within the allowed size.
> If not log the flow that would trigger this problem and do not program
> it. This isn't a self-healing process, but the chance of this happening
> are very slim. Also, any flow that is bigger than allowed size is OVN
> bug, and it should be fixed.
>
> Reported-at: https://bugzilla.redhat.com/1955167
> Signed-off-by: Ales Musil <amu...@redhat.com>
> ---
>  controller/ofctrl.c | 74 ++++++++++++++++++++++++++++++++-------------
>  1 file changed, 53 insertions(+), 21 deletions(-)
>
> diff --git a/controller/ofctrl.c b/controller/ofctrl.c
> index 64a444ff6..bb42d474f 100644
> --- a/controller/ofctrl.c
> +++ b/controller/ofctrl.c
> @@ -1769,6 +1769,16 @@ ovn_flow_log(const struct ovn_flow *f, const char
> *action)
>      }
>  }
>
> +static void
> +ovn_flow_log_size_err(const struct ovn_flow *f)
> +{
> +    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> +
> +    char *s = ovn_flow_to_string(f);
> +    VLOG_ERR_RL(&rl, "The FLOW_MOD message is too big: %s", s);
> +    free(s);
> +}
> +
>  static void
>  ovn_flow_uninit(struct ovn_flow *f)
>  {
> @@ -1888,15 +1898,27 @@ encode_bundle_add(struct ofpbuf *msg, struct
> ofputil_bundle_ctrl_msg *bc)
>      return ofputil_encode_bundle_add(OFP15_VERSION, &bam);
>  }
>
> -static void
> +static bool
>  add_flow_mod(struct ofputil_flow_mod *fm,
>               struct ofputil_bundle_ctrl_msg *bc,
>               struct ovs_list *msgs)
>  {
>      struct ofpbuf *msg = encode_flow_mod(fm);
>      struct ofpbuf *bundle_msg = encode_bundle_add(msg, bc);
> +
> +    uint32_t flow_mod_len = msg->size;
> +    uint32_t bundle_len = bundle_msg->size;
> +
>      ofpbuf_delete(msg);
> +
> +    if (flow_mod_len > UINT16_MAX || bundle_len > UINT16_MAX) {
> +        ofpbuf_delete(bundle_msg);
> +
> +        return false;
> +    }
> +
>      ovs_list_push_back(msgs, &bundle_msg->list_node);
> +    return true;
>  }
>
>  /* group_table. */
> @@ -2227,15 +2249,18 @@ installed_flow_add(struct ovn_flow *d,
>  {
>      /* Send flow_mod to add flow. */
>      struct ofputil_flow_mod fm = {
> -        .match = d->match,
> -        .priority = d->priority,
> -        .table_id = d->table_id,
> -        .ofpacts = d->ofpacts,
> -        .ofpacts_len = d->ofpacts_len,
> -        .new_cookie = htonll(d->cookie),
> -        .command = OFPFC_ADD,
> +            .match = d->match,
> +            .priority = d->priority,
> +            .table_id = d->table_id,
> +            .ofpacts = d->ofpacts,
> +            .ofpacts_len = d->ofpacts_len,
> +            .new_cookie = htonll(d->cookie),
> +            .command = OFPFC_ADD,
>      };
> -    add_flow_mod(&fm, bc, msgs);
> +
> +    if (!add_flow_mod(&fm, bc, msgs)) {
> +        ovn_flow_log_size_err(d);
> +    }
>  }
>
>  static void
> @@ -2245,12 +2270,12 @@ installed_flow_mod(struct ovn_flow *i, struct
> ovn_flow *d,
>  {
>      /* Update actions in installed flow. */
>      struct ofputil_flow_mod fm = {
> -        .match = i->match,
> -        .priority = i->priority,
> -        .table_id = i->table_id,
> -        .ofpacts = d->ofpacts,
> -        .ofpacts_len = d->ofpacts_len,
> -        .command = OFPFC_MODIFY_STRICT,
> +            .match = i->match,
> +            .priority = i->priority,
> +            .table_id = i->table_id,
> +            .ofpacts = d->ofpacts,
> +            .ofpacts_len = d->ofpacts_len,
> +            .command = OFPFC_MODIFY_STRICT,
>      };
>      /* Update cookie if it is changed. */
>      if (i->cookie != d->cookie) {
> @@ -2259,7 +2284,7 @@ installed_flow_mod(struct ovn_flow *i, struct
> ovn_flow *d,
>          /* Use OFPFC_ADD so that cookie can be updated. */
>          fm.command = OFPFC_ADD;
>      }
> -    add_flow_mod(&fm, bc, msgs);
> +    bool result = add_flow_mod(&fm, bc, msgs);
>
>      /* Replace 'i''s actions and cookie by 'd''s. */
>      mem_stats.installed_flow_usage -= i->ofpacts_len - d->ofpacts_len;
> @@ -2267,6 +2292,10 @@ installed_flow_mod(struct ovn_flow *i, struct
> ovn_flow *d,
>      i->ofpacts = xmemdup(d->ofpacts, d->ofpacts_len);
>      i->ofpacts_len = d->ofpacts_len;
>      i->cookie = d->cookie;
> +
> +    if (!result) {
> +        ovn_flow_log_size_err(i);
> +    }
>  }
>
>  static void
> @@ -2275,12 +2304,15 @@ installed_flow_del(struct ovn_flow *i,
>                     struct ovs_list *msgs)
>  {
>      struct ofputil_flow_mod fm = {
> -        .match = i->match,
> -        .priority = i->priority,
> -        .table_id = i->table_id,
> -        .command = OFPFC_DELETE_STRICT,
> +            .match = i->match,
> +            .priority = i->priority,
> +            .table_id = i->table_id,
> +            .command = OFPFC_DELETE_STRICT,
>

Oh I don't know what happened with the formatting. I'll fix that in v2
sorry about the noise.


>      };
> -    add_flow_mod(&fm, bc, msgs);
> +
> +    if (!add_flow_mod(&fm, bc, msgs)) {
> +        ovn_flow_log_size_err(i);
> +    }
>  }
>
>  static void
> --
> 2.41.0
>
>

-- 

Ales Musil

Senior Software Engineer - OVN Core

Red Hat EMEA <https://www.redhat.com>

amu...@redhat.com    IM: amusil
<https://red.ht/sig>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to